Python基础13-文件处理

目录

用内置函数open打开文件

以文本方式打开文件

只读模式r

只写模式w

追加模式a

覆盖模式+

以二进制方式打开文件

以二进制方式读

以二进制方式写

open函数的newline参数

file object的方法

tell显示当前光标的位置

seek控制光标的移动

truncate切片文件


用内置函数open打开文件

open打开文件,返回文件句柄。通过句柄关闭文件。Python默认使用utf-8编码,但是open函数不是,open函数会检测当前操作系统的编码。read读取文件的全部内容。

# file1
# 苟利国家生死以
# 岂因祸福避趋之
f = open('file1.txt', encoding='utf-8')
data = f.read()
print(data)
f.close()

以文本方式打开文件

只读模式r

打开文件有不同的模式。用readable和writable方法判断是否可读写。

只读模式r,如果进行写操作会报错。只读是默认模式。用read读取全部内容。用readline读取一行。用readlines读取所有行放在一个列表里。

# file2
# 生不逢时
# 爱不逢人
# 所到之处
# 皆是命数
f = open('file2.txt')
print('line1:--->', f.readline(), end='')
print('line2:--->', f.readline(), end='')
f.close()

f = open('file2.txt')
ss = f.readlines()
print(type(ss), ss)
# <class 'list'> ['生不逢时\n', '爱不逢人\n', '所到之处\n', '皆是命数\n']
for s in ss:
    print(s, end='')
    pass
f.close()

只写模式w

只写模式w,如果进行读操作会报错。如果文件不存在,那么会创建一个新文件。如果文件已经存在,那么会在打开文件时清空文件内容,再进行后续操作,慎重慎重。write方法只写但不加空格,writelines方法入参一个字符串列表,每个元素写一下,自己加换行。注意只能写字符串!

f = open('file3.txt', 'w', encoding='utf-8')
f.write('我是身经百战了!')
f.write('见的多了!\n')
f.write('西方哪一个国家我没有去过啊?\n')
f.close()
# file3内容是两行,写write需要自己加换行
# 我是身经百战了!见的多了!
# 西方哪一个国家我没有去过啊?

f = open('file3.txt', 'w', encoding='utf-8')
seq = ['我是身经百战了!\n', '见的多了!\n', '西方哪一个国家我没有去过啊?\n']
f.writelines(seq)
f.close()
# 我是身经百战了!
# 见的多了!
# 西方哪一个国家我没有去过啊?

追加模式a

追加模式a,写的内容写到文件最后,不清空文件原有内容。适用于写日志。

f = open('file4.txt', 'a', encoding='utf-8')
f.write('写到文件字后\n')
f.close()

覆盖模式+

可读可写,写就直接从头开始覆盖已有内容。

f = open('file4.txt', mode='r+', encoding='gbk')
print(f.readable(), f.writable())
# True True
f.close()

以二进制方式打开文件

应用中,以二进制方式打开文件的情况可能更多,图片、视频、音频等都是以二进制方式读写的。

以二进制方式读

以文本方式打开文件是默认方式,还可以以二进制方式打开,也就是mode='b'。因为是以二进制方式打开,不再涉及编码,不能用 encoding入参指定编码方式。此时,read读取的数据都是一个一个的字节。如果要将一个一个的字节转换成可读的文字,那么需要进行解码decode。

# file3
# 我是身经百战了!
# 见的多了!
# 西方哪一个国家我没有去过啊?
f = open('file3.txt', mode='rb')
data = f.read()
print(data)
# b'\xe6\x88\x91\xe6\x98\xaf\xe8\xba\xab\xe7\xbb\x8f\xe7\x99\xbe\xe6\x88\x98\xe4\xba\x86\xef\xbc\x81\r\n\xe8\xa7\x81\xe7\x9a\x84\xe5\xa4\x9a\xe4\xba\x86\xef\xbc\x81\r\n\xe8\xa5\xbf\xe6\x96\xb9\xe5\x93\xaa\xe4\xb8\x80\xe4\xb8\xaa\xe5\x9b\xbd\xe5\xae\xb6\xe6\x88\x91\xe6\xb2\xa1\xe6\x9c\x89\xe5\x8e\xbb\xe8\xbf\x87\xe5\x95\x8a\xef\xbc\x9f\r\n'
print(data.decode('utf-8'))
# 解码为可读的字符
f.close()

以二进制方式写

以二进制方式写,mode='wb'或'ab'。因为是以二进制方式打开,不再涉及编码,不能用 encoding入参指定编码方式。此时write写入的都是一个一个字节,,不能直接写字符串,而要将字符串编码转换成字节流。

f = open('file6.txt', mode='wb')
# 以二进制方式写,不能直接写字符串,而要将字符串编码转换成字节流
f.write('苟利国家生死以,岂因祸福避趋之。'.encode('utf-8'))
f.close()

open函数的newline参数

在大多数操作系统里面,换行是\n。然而,windows里面换行是\r\n。

以文本模式打开文件时,newline参数对换行符进行转换。如果不指定,那么换行符都是\n。如果传入newline='',那么换行符按照操作系统转换为特定符号,windows下换行符转换为\r\n。

f = open('file1.txt', mode='r', encoding='utf-8')
d = f.readlines()
print(d)
# ['苟利国家生死以\n', '岂因祸福避趋之\n']
f.close()

f = open('file1.txt', mode='r', encoding='utf-8', newline='')
d = f.readlines()
print(d)
# ['苟利国家生死以\r\n', '岂因祸福避趋之\r\n']
f.close()

file object的方法

tell显示当前光标的位置

文件以utf-8编码的文本形式打开,刚打开光标在0。读取一行,共7个汉字,因为utf-8编码汉字用3个字节,windows换行\r\n占两个字节,所以移动了3*7+2=23个字节。

# file1.txt
# 苟利国家生死以
# 岂因祸福避趋之
f = open('file1.txt', mode='r', encoding='utf-8')
print(f.tell())
# 0
d = f.readline()
print(d, end='')
# 苟利国家生死以
print(f.tell())
# 23
f.close()

seek控制光标的移动

除了read方法,其他光标的移动都是以字节为单位,seek也是一样。read读取3个字符“苟利国”,seek将光标移动到3个字节,也就是utf-8一个字符的位置,再读取3个字符“利国家”。

如果,用seek方法的第二个参数来控制seek的方式,那么必须以二进制方式打开文件,此时read读取的数列也是字节数。

seek第二个参数0,表示从文件开头开始seek,必须seek正数字节。

seek第二个参数1,表示从当前位置开始seek,可以seek正数、负数。

seek第二个参数2,表示从文件结尾开始seek,必须seek负数字节。

# file1.txt
# 苟利国家生死以
# 岂因祸福避趋之
f = open('file1.txt', mode='rb')
# 刚打开,光标位置为0,读取9个字节,得到 苟利国
d = f.read(9)
print(d.decode('utf-8'))
# 苟利国

# seek从头开始3个字节,再读取9个字节,得到 利国家
f.seek(3)
d = f.read(9)
print(d.decode('utf-8'))
# 利国家

# whence=1,也就是从当前位置11个字节,跳过生死以和\r\n
# 读取9个字节,得到 岂因祸
f.seek(11, 1)
d = f.read(9)
print(d.decode('utf-8'))
# 岂因祸

# whence=2,也就是从文件最后倒着读取,跳过最后的\r\n和避趋之
# 读取9个字节,得到 避趋之
f.seek(-11, 2)
d = f.read(9)
print(d.decode('utf-8'))
# 避趋之
f.close()

seek方法的一个应用就是读取文件的最后一行。方法是从文件结尾,倒着seek再读取。如果不是读取多行,那么增大倒着seek的范围,直到能读取多行。打印最后一行。

# 如何读取文件的最后一行
# 方法是尝试读取多行,如果不是多行,那么增加读取范围
# 增加范围不一定用+1的办法,*2扩大一倍的办法更快
# file2.txt 用gbk编码
# 生不逢时
# 爱不逢人
# 所到之处
# 皆是命数
f = open('file2.txt', mode='rb')
offs = -1
while True:
    f.seek(offs, 2)
    d = f.readlines()
    if len(d) > 1:
        print('最后一行是:%s' % d[-1].decode('gbk'))
        break
        pass
    offs *= 2
f.close()

truncate切片文件

truncate是写操作,因此open文件的时候必须用'+',但是不能用'w+'。同样也是以字节为单位。

# file1.txt
# 苟利国家生死以
# 岂因祸福避趋之
f = open('file1.txt', mode='r+', encoding='utf-8')
f.truncate(12)
f.close()
# file1.txt 只剩下 苟利国家 四个字

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章