欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 31天Python入门——第13天:文件操作

31天Python入门——第13天:文件操作

2025/3/31 20:09:39 来源:https://blog.csdn.net/weixin_57544072/article/details/146455834  浏览:    关键词:31天Python入门——第13天:文件操作

在这里插入图片描述

你好,我是安然无虞。

文章目录

    • 文件操作
      • 1. 文件的概念
      • 2. python中的文件读取
        • open函数的参数
        • 文本的读取
      • 3. python中的文件写入
        • 补充: 文件指针相关
      • 4. with语句实现文件读写
        • 扩展学习: json相关
      • 5. 补充练习

在这里插入图片描述

文件操作

1. 文件的概念

  1. 文件的概念和分类
    • 文件是用于存储数据的一种持久化媒介.
    • 在计算机中, 文件分为文本文件和二进制文件两种类型.
    • 文本文件由字符组成, 可以使用文本编辑器打开并阅读.
    • 二进制文件由字节组成, 包含非文本数据, 如图像、音频和视频等.

在日常生活, 工作中, 文件的操作主要包括: 创建文件, 打开, 关闭, 读, 写.

2. python中的文件读取

使用 open() 函数打开文件, 接受文件路径和打开模式, 编码等作为参数.
open函数会返回一个对象,我们可以称之为文件对象.

文件的打开,分为 文本模式 和 二进制模式:

通常,对文本文件,都是以文本模式打开
文本模式打开文件后,我们的程序读取到的内容都是字符串对象,写入文件时传入的也是字符串对象.

f = open(file, mode, encoding)
# file: 需要打开的目标文件(包含路径和文件名), 类型是字符串.
# mode: 设置打开文件的模式. 读, 写, 追加写. 类型是字符串.
# encoding: 编码. 一般使用utf-8.# 使用 close() 方法关闭文件, 释放资源.
f.close()
open函数的参数

要读写文件,首先要通过内置函数open 打开文件,获得文件对象.

函数open的参数如下:

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异常.
# 1. 相对路径.
# 2. 绝对路径.
# f:文件对象, 它是一个迭代器.
f = open(r".\test.png", 'rb', encoding='utf-8') # 读取图片,应该是二进制数据 
content = f.read()
print(content)f.close()
文本的读取
  1. 使用 read() 方法读取整个文本文件的内容.
  2. 使用 readline() 方法逐行读取文本文件的内容, 每次调用 readline()方法, 它会返回文件中的下一行作为一个字符串.当到达文件末尾时, 它会返回一个空字符串. 可以在循环中使用 readline() 方法来逐行处理文件内容. -> 注意换行符也读取出来了
  3. readlines(): 这个方法用于一次性读取整个文件内容, 并将每一行作为一个字符串存储在一个列表中.它会返回一个包含所有行的列表, 每行作为一个元素. 你可以直接遍历这个列表或使用索引访问特定行.

以上3个方法都可以接收一个参数,它们接受一个可选的参数用于指定要读取的字符数或字节数(是字符数还是字节数和读取的文件类型相关联), 指定要读取的最大字符数或字节数.如果省略参数或指定为负数(默认值), 则会读取全部内容.返回值是一个包含读取行内容的字符串.

# 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+’以二进制模式以读写方式打开文件.文件的指针将会放在文件的末尾.如果文件不存在, 则会创建一个新文件.
# 写入刚刚读取到的图片(二进制数据)
f = open('./jietu.png', 'wb')
f.write(b'xxxxxx')
f.close()# 查看是否生成了这个图片, 双击图片是否正常显示
# 追加写
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)
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’, 需要怎么做: 我们可以手动操作文件指针

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() 方法.

示例:

# 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字符串转化为字典对象
# 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 jsondata_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字符串
# json.dumps(): 将字典对象转化为json字符串import jsondata_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.实现一个通讯录的功能. 存储的联系人需要永久存储. (提示: 将联系人存储到文件.)
通讯录的基本功能都要具备.

  1. 添加联系人.
  2. 删除联系人.
  3. 查询指定联系人.
  4. 查看所有的联系人.
  5. 退出通讯录.
import jsondef 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('已退出通讯录管理系统')breakmenu()

2.图片文件类型识别
你们公司有一批图片文件,不小心被管理人员把扩展名都去掉了.
这批图片文件中有的是png文件,有的是jpg文件.
png文件的开头一定是 这样的 89 50 4e 47 0d 0a 1a 0a 8个字节

现在要求你写一个函数,参数是图片文件的路径,函数根据文件的开头8个字节的信息,判断该文件是不是png文件.

如果是,打印出 png, 否则打印出 jpg.

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')
遇见安然遇见你,不负代码不负卿。
谢谢老铁的时间,咱们下篇再见~

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词