跳转至

Python 中读写文件的细节\#

记录一下使用Python读写文件时各参数的含义,以及它们的区别

缘起\#

前面在爬取马里奥兄弟的谱子的时候碰到了这样一个问题:

截屏2023-05-07 16.41.42

立刻意识到了这里爬取的两种文件有差别,于是想到了爬取文件的格式和读写,找到了下面的文章,说明得比较清楚

response.text 和response.content\#

response.text\#

类型:str

解码类型:根据HTTP头部对响应的编码做出有根据的推测,推测的文本编码

如何修改编码方式:

response.encoding = "gbk"

response.content\#

类型:bytes

解码类型:没有指定

如何修改编码方式:

response.content.decode("utf8")

差别\#

两者区别在于,content中间存的是字节码,而text中存的是Beautifulsoup根据猜测的编码方式将content内容编码成字符串 直接输出content,会发现前面存在b这样的标志,这是字节字符串的标志,而text是,没有前面的b,对于纯ascii码,这两个可以说一模一样,对于其他的文字,需要正确编码才能正常显示。大部分情况建议使用.text,因为显示的是汉字,但有时会显示乱码,这时需要用.content.decode(‘utf-8’),中文常用utf-8和GBK,GB2312等。这样可以手工选择文字编码方式

所以简而言之,.text是现成的字符串,.content是字节码还要编码,但是.text不是所有时候显示都正常,这是就需要用.content进行手动编码

打开文件\#

有的时候会用wb打开文件,有的时候又用w打开文件,有什么区别呢?

在windows中的换行符是\r\n 在python代码中, 如果以w方式写入:

f = open('./abcd', "w")
f.write('abc\nabcd')
f.close()

文本w方式写入时, 遇到\n自动替换成\r\n,

以二进制文本读:

f = open('./abcd', 'rb')
print(f.read())
结果:

b'abc\r\nabcd'

以文本读:

f = open('./abcd', 'r')
print(f.read())

结果:

abc
abcd

综上可知, 只文本w方式写入时, 遇到\n自动替换成\r\n, 所以用二进制读取时, 显示\r\n的格式, 自然以文本读时, 会自动换行

如果以wb方式写入:

f = open('./abcd', "wb")
f.write('abc\nabcd'.encode("utf-8"))
f.close()

以二进制文本读:
f = open('./abcd', "rb")
print(f.read())

结果: 'abc\nabcd'

以文本读:
f = open('./abcd', "r")
print(f.read())

结果(换行): 
abc
abcd

因为这种情况是二进制方式写入的, 所以只写入了一个\n, 而只有一个\n在windows中 并不会被识别为换行符, 所以当以rb的方式读取时, 结果是 'abc\nabcd' 当以r的方式读取时, 又自动将\n识别成换行符, 所以结果时

对于Python3环境:

r:Python将会按照编码格式进行解析,read()操作返回的是str

rb:也即binary moderead()操作返回的是bytes

也就是说, 如果以文本方式写入的文件, 无需制定编码. 而以二进制文本写入时, 由于写入的内容要求为bytes,所以通过str.encode('charset')来返回bytes

open函数\#

python open() 函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。

函数语法\#

open(name[, mode[, buffering]])

参数说明:

  • name : 一个包含了你要访问的文件名称的字符串值。
  • mode : mode 决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读®。
  • buffering : 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。

不同模式打开文件的完全列表:

模式 描述
t 文本模式 (默认)。
x 写模式,新建一个文件,如果该文件已存在则会报错。
b 二进制模式。
+ 打开一个文件进行更新(可读可写)。
U 通用换行模式(不推荐)。
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

file 对象方法\#

  • file.read([size]):size 未指定则返回整个文件,如果文件大小 >2 倍内存则有问题,f.read()读到文件尾时返回""(空字串)。

  • file.readline():返回一行。

  • file.readlines([size]) :返回包含size行的列表, size 未指定则返回全部行。

  • for line in f: print line :通过迭代器访问。

  • f.write("hello\n"):如果要写入字符串以外的数据,先将他转换为字符串。

  • f.tell():返回一个整数,表示当前文件指针的位置(就是到文件头的字节数)。

  • f.seek(偏移量,[起始位置]):用来移动文件指针。

  • 偏移量: 单位为字节,可正可负

  • 起始位置: 0 - 文件头, 默认值; 1 - 当前位置; 2 - 文件尾

  • f.close() 关闭文件

更多内容参考:Python File(文件) 方法