
|----------------|
| 你好,我是安然无虞。 |
文章目录

文件操作
1. 文件的概念
- 文件的概念和分类
- 文件是用于存储数据的一种持久化媒介.
- 在计算机中, 文件分为文本文件和二进制文件两种类型.
- 文本文件由字符组成, 可以使用文本编辑器打开并阅读.
- 二进制文件由字节组成, 包含非文本数据, 如图像、音频和视频等.
在日常生活, 工作中, 文件的操作主要包括: 创建文件, 打开, 关闭, 读, 写.
2. python中的文件读取
使用 open()
函数打开文件, 接受文件路径和打开模式, 编码等作为参数.
open函数会返回一个对象,我们可以称之为文件对象.
文件的打开,分为 文本模式 和 二进制模式:
通常,对文本文件,都是以文本模式打开
文本模式打开文件后,我们的程序读取到的内容都是字符串对象,写入文件时传入的也是字符串对象.
pythonf = open(file, mode, encoding) # file: 需要打开的目标文件(包含路径和文件名), 类型是字符串. # mode: 设置打开文件的模式. 读, 写, 追加写. 类型是字符串. # encoding: 编码. 一般使用utf-8. # 使用 close() 方法关闭文件, 释放资源. f.close()
open函数的参数
要读写文件,首先要通过内置函数open 打开文件,获得文件对象.
函数open的参数如下:
python
open(
file,
mode='r',
buffering=-1,
encoding=None,
errors=None,
newline=None,
closefd=True,
opener=None
)
其中下面这3个参数是我们常用的:
-
参数 file
file参数指定了要打开文件的路径.
可以是相对路径,比如 'log.txt', 就是指当前工作目录下面的log.txt 文件 也可以是绝对路径,比如 'd:\project\log\log.txt'
-
参数 mode
mode参数指定了文件打开的 模式 ,打开文件的模式 决定了可以怎样操作文件
-
参数 encoding
encoding 参数指定了读写文本文件时,使用的 字符编解码 方式
调用open函数时,如果传入了encoding参数值:
- 后面调用write写入字符串到文件中,open函数会使用指定encoding编码为 字节串;
- 后面调用read从文件中读取内容,open函数会使用指定encoding解码为字符串对象
如果调用的时候没有传入encoding参数值,open函数会使用系统缺省字符编码方式. 比如在中文的Windows系统上,就是使用cp936(就是gbk编码).
建议大家编写代码 读写文本文件时,都指定该参数的值.
常见的打开模式包括: 读取模式('r')、写入模式('w')、追加模式('a')和二进制模式('b')
上述代码中的f是open函数返回的文件对象.
以下是关于文件读取的常用模式.
模式 描述 'r' 默认模式, 以只读方式打开文件.文件的指针 将会放在文件的开头 .如果文件不存在, 将会引发 FileNotFoundError
异常.'rb' 以二进制模式以只读方式打开文件.适用于读取 二进制数据, 如图像、音频等.
'r+' 以读写方式打开文件.文件的指针将会放在文件的开头. 这里是不会清空文件内容的. 如果文件不存在, 将会引发 FileNotFoundError
异常.'rb+' 以二进制模式以读写方式打开文件.文件的指针将会放在文件的开头.如果文件不存在, 将会引发 FileNotFoundError
异常.
python
# 1. 相对路径.
# 2. 绝对路径.
# f:文件对象, 它是一个迭代器.
f = open(r".\test.png", 'rb', encoding='utf-8') # 读取图片,应该是二进制数据
content = f.read()
print(content)
f.close()
文本的读取
- 使用
read()
方法读取整个文本文件的内容
. - 使用
readline()
方法逐行读取文本文件的内容, 每次调用 readline()方法, 它会返回文件中的下一行作为一个字符串.当到达文件末尾时, 它会返回一个空字符串. 可以在循环中使用 readline() 方法来逐行处理文件内容. -> 注意换行符也读取出来了 readlines()
: 这个方法用于一次性读取整个文件内容, 并将每一行作为一个字符串存储在一个列表中.它会返回一个包含所有行的列表, 每行作为一个元素. 你可以直接遍历这个列表或使用索引访问特定行.
以上3个方法都可以接收一个参数,它们接受一个可选的参数用于指定要读取的字符数或字节数
(是字符数还是字节数和读取的文件类型相关联), 指定要读取的最大字符数或字节数.如果省略参数或指定为负数(默认值), 则会读取全部内容.返回值是一个包含读取行内容的字符串.
python
# f:文件对象, 它是一个迭代器.
f = open(r".\test.txt", 'r', encoding='utf-8')
content = next(f)
print(content)
for text in f:
print(f'文件内容: {text}')
# content = f.read(10)
content = f.readline(10) # 也是根据读取的字符数来的
content = f.readline(100) # 只将当前行的内容给出, 并没有给出下一行
# 对于readline()来说, 当读取的字符数小于当前行时截断显示, 当大于时也只是显示当前行的内容
print(content)
print(content)
lines = f.readlines(57)
print(lines)
line = True
while line:
line = f.readline()
print(line.strip())
f.close()
3. python中的文件写入
write() : 使用
write()
方法向文本文件写入文本内容, 调用write将内容写入到缓冲区.flush() : 调用
flush()
将缓冲区的内容写入到磁盘.close() : 调用
close()
关闭文件的同时也会将缓冲区的内容写入到磁盘. 所以调用close()的话, 可以不需要使用到flush().
以下是关于文件写入的常用模式.r
w
a
b
+: 可读可写
思考一下: r+ 和 a 的区别: 后面会讲解到.
模式 描述 'w' 以写入方式打开文件.如果文件已存在, 则会被清空;如果文件不存在, 则会创建一个新文件. 'wb' 以二进制模式以写入方式打开文件.适用于写入二进制数据, 如图像、音频等. 'w+' 以读写方式打开文件.如果文件已存在, 则会被清空;如果文件不存在, 则会创建一个新文件. 'wb+' 以二进制模式以读写方式打开文件.如果文件已存在, 则会被清空;如果文件不存在, 则会创建一个新文件. 'a' 以追加方式打开文件.文件的指针将会放在文件的末尾.如果文件不存在, 则会创建一个新文件. 'ab' 以二进制模式以追加方式打开文件.适用于追加二进制数据. 'a+' 以读写方式打开文件.文件的指针将会放在文件的末尾.如果文件不存在, 则会创建一个新文件. 'ab+' 以二进制模式以读写方式打开文件.文件的指针将会放在文件的末尾.如果文件不存在, 则会创建一个新文件.
python
# 写入刚刚读取到的图片(二进制数据)
f = open('./jietu.png', 'wb')
f.write(b'xxxxxx')
f.close()
# 查看是否生成了这个图片, 双击图片是否正常显示
python
# 追加写
f = open('./text.txt', 'a')
f.write('hello world\n') # 注意这个'\n'的处理, 可以在追加写的时候自动换行
f.close()
补充: 文件指针相关
LF 和 CRLF 是两种不同的行结束符,它们在不同操作系统和场景下有着不同的用途和特点:
- LF 是 "Line Feed" 的缩写,表示换行符. 在文本文件中,它用于表示一行的结束,并将光标移动到下一行的开头. (\n)
- CRLF 是 "Carriage Return and Line Feed" 的缩写,表示回车符和换行符的组合。它是由两个字符组成的,先是一个回车符(CR),将光标移动到当前行的开头,然后是一个换行符(LF),将光标移动到下一行的开头. (\r\n)
python
f = open('./test.txt', 'a')
n = f.tell() # n为当前文件指针所在的位置
print(n)
# test.txt 内容是'hello world'一行内容
# 用LF其实就是 'hello world\n'
# 用CRLF其实就是 'hello world\r\n'
# 如果将上面的'a'换成'r'的话: 打印出来的n就是0, 因为以r的方式打开文件会将文件指针放到文件的开头
现在有一个需求, 将文件中的'world'换成'python', 需要怎么做: 我们可以手动操作文件指针
python
f = open('./test.txt', 'a')
f.seek(6) # 将指针移动到第6个字符处
f.truncate() # 截断 - 将文件指针后的字符全部截掉
f.write('python\n') # 这样就可以将原来的 hello world 改为 hello python
f.close()
4. with语句实现文件读写
with
语句可以自动管理文件的打开和关闭, 无需显式调用close()
方法.
示例:
python# as关键字后面的变量f实际上就是文件对象 with open('test.txt', 'r') as f: content = f.read() print(content)
使用
with
语句可以更安全和高效地进行文件读写操作, 并确保在读写完成后正确地关闭文件.无需手动调用close()
方法.
注意:
with 语句本身不会限制变量的作用域.
变量的作用域取决于它被定义的位置(全局作用域或局部作用域)
- 如果 with 语句块位于全局作用域中,那么在 with 语句块中定义的变量(如 content)也是全局变量,可以在整个模块中访问.
- 如果 with 语句块位于函数内部,那么在 with 语句块中定义的变量是局部变量,只能在该函数内部访问.
所以上面的代码中可以在with语句外使用content变量.
扩展学习: json相关
JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。
它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
- 在Python中,JSON可以表示为字符串,因为在传输或存储时,JSON数据需要以字符串的形式进行序列化.
- 将Python对象转换为JSON字符串以便传输或存储. 然后,在需要时,可以将JSON字符串反序列化为Python对象.
JSON的语法规则与Python中的字典(dict)非常相似,因此我们可以将Python中的字典转换为JSON格式,以便在不同的系统或应用程序之间进行数据交换.
总结起来,JSON是一种数据交换格式,可以用于表示数据,并且在Python中可以进行JSON与Python对象之间的相互转换.
- json.loads(): 将json字符串转化为字典对象
python
# json.loads(): 将json字符串转化为字典对象
json_string = """
{
"name": "John",
"age": 25,
"xxx": null,
"isStudent": true,
"hobbies": ["reading", "playing", "traveling"],
"address": {
"street": "123 Main St",
"city": "New York"
},
"scores": [85, 92, 78, 90]
}
"""
import json
data_dict = json.loads(json_string) # 将json字符串转化为字典对象
print(type(data_dict)) # <class 'dict'>
print(data_dict) # {'name': 'John', 'age': 25, 'xxx': None, 'isStudent': True, 'hobbies': ['reading', 'playing', 'traveling'], 'address': {'street': '123 Main St', 'city': 'New York'}, 'scores': [85, 92, 78, 90]}
score = data_dict.get('scores')
print(f'分数是: {score}') # 分数是: [85, 92, 78, 90]
- json.dumps(): 将字典对象转化为json字符串
python
# json.dumps(): 将字典对象转化为json字符串
import json
data_dic = {
"name": "张三",
"age": 25,
"xxx": None,
"isStudent": True,
"hobbies": ["reading", "playing", "traveling"],
"address": {
"street": "123 Main St",
"city": "New York"
},
"scores": [85, 92, 78, 90]
}
with open("./test.txt", 'w', encoding='utf8') as f:
f.write(json.dumps(data_dic, ensure_ascii=False)) # json.dumps() 将字典对象转化为json字符串
5. 补充练习
1.实现一个通讯录的功能. 存储的联系人需要永久存储. (提示: 将联系人存储到文件.)
通讯录的基本功能都要具备.
- 添加联系人.
- 删除联系人.
- 查询指定联系人.
- 查看所有的联系人.
- 退出通讯录.
python
import json
def query_all():
with open("./contact.txt", 'r', encoding='utf8') as f:
content = f.read()
if content:
# 如果存在, 就要展示所有的联系人.
print('为您查询到的所有联系人如下:')
json_data = json.loads(content)
for key, val in json_data.items():
print(f'{key}: {val}')
else:
print(f'该通讯录目前没有联系人, 请先添加联系人')
def query_contact():
name = input("请输入想要查询的联系人姓名:")
with open("./contact.txt", 'r', encoding='utf8') as f:
content = f.read()
if content:
# 如果存在, 就要做查询操作.
json_data = json.loads(content)
phone = json_data.get(name)
print(f'为您查询到的指定联系人{name}的电话是: {phone}')
else:
print(f'未找到指定联系人: {name}')
def del_contact():
name = input("请输入想要删除的联系人姓名:")
with open("./contact.txt", 'r+', encoding='utf8') as f:
content = f.read()
if content:
# 如果存在, 就要做删除操作.
json_data = json.loads(content)
json_data.pop(name)
f.seek(0)
f.truncate()
f.write(json.dumps(json_data, ensure_ascii=False))
else:
# 如果不存在, 就没办法删了.
print(f'未找到指定联系人: {name}')
def add_contact():
name = input("请输入联系人姓名:")
phone = input("请输入联系人电话:")
contact_dict = {
name: phone
}
# 将联系人信息存储到文件 - 可以使用字典
with open("./contact.txt", 'r+', encoding='utf8') as f:
content = f.read() # 此时文件指针跑到了文件内容的末尾
if content:
json_data = json.loads(content)
json_data.update(contact_dict)
else:
json_data = contact_dict
# 将文件指针移动到文件开头
f.seek(0)
f.truncate()
f.write(json.dumps(json_data, ensure_ascii=False))
def menu():
print("欢迎使用通讯录管理系统")
print("------welcome-----")
print("菜单选项:")
print("1. 添加联系人.")
print("2. 删除联系人.")
print("3. 查询指定联系人.")
print("4. 查看所有的联系人.")
print("5. 退出通讯录.")
while True:
choice = int(input("请输入您想要操作的选项:"))
if choice == 1:
add_contact()
elif choice == 2:
del_contact()
elif choice == 3:
query_contact()
elif choice == 4:
query_all()
elif choice == 5:
print('已退出通讯录管理系统')
break
menu()
2.图片文件类型识别
你们公司有一批图片文件,不小心被管理人员把扩展名都去掉了.
这批图片文件中有的是png文件,有的是jpg文件.
png文件的开头一定是 这样的 89 50 4e 47 0d 0a 1a 0a 8个字节
现在要求你写一个函数,参数是图片文件的路径,函数根据文件的开头8个字节的信息,判断该文件是不是png文件.
如果是,打印出 png, 否则打印出 jpg.
python
def tellPngFile(fp):
f = open(fp, 'rb')
content = f.read(8) # 只读出来文件开头8个字节即可
f.close()
if content == b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a':
print('png')
else:
print('jpg')
tellPngFile('download.png')
|----------------------|
| 遇见安然遇见你,不负代码不负卿。 |
| 谢谢老铁的时间,咱们下篇再见~ |