这篇文章介绍Python中文件操作最常用的读文件相关的函数和其中某些易错点。
1.函数功能介绍
可以先运行下面的例子,然后对比运行结果理解函数功能!
tell():返回当前的指针相对于文件开始的偏移量
-utf8编码下:如果是中文的话,一个字的偏移量是3。
-每一行的末尾其实是\r\n,代表了2个偏移量
seek(offset, from):定位文件指针
offset:偏移量。
-如果是文本文件
-需满足以下条件:from=0时,offset>=0;from=1或2时,offset必须为0;
-若其中含有中文字符,注意from=0时,指针不要对一个中文字符的二进制编码(包含3个偏移量)中间,否则报错。
一般较难确定正确的位置,所以建议直接设置为0
-如果是对二进制文件,需满足以下条件:
-from=0时,offset>=0;
-from=1,offset可任意(不要超过总文件的范围);
-from=2,offset<=0(不要超过总文件的范围);
from:方向
0:表示文件开头
1:表示当前位置
2:表示文件末尾
read(size):读取文件中size长度的字符串
-size表示从当前指针位置开始读取字符的长度。如果无参数,则默认读取该文件全部数据
-utf8编码的文本文件下:中文、英文、换行的每个字符长度都代表1
-二进制下:utf8编码后以二进制读取,每个中文代表长度3,读取长度与文件指针变化一样。
如:xx.read(10),文件指针就+10
readline(size) :读取行
-从当前指针位置开始读一行,如果定义了size,有可能返回的只是一行的一部分
readlines(size) :读取多行
-从当前指针位置开始把文件每一行作为一个list的一个成员,并返回这个list。
-其实它的内部是通过循环调用readline()来实现的。
-如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分。
-如果最后指针停留在某一行的中间,那么自动将该行全部读取。也就是说执行完该函数之后,文件指针总停留在下一行开头(对行取整)
2.函数使用
例子:
utf8编码的文本文件内容如下:
这是第一行数据
abcdefghijk0
这是第三行数据
abcdefghijk2
abcdefghijk3
abcdefghijk4
abcdefghijk5
abcdefghijk6
abcdefghijk7
abcdefghijk8
abcdefghijk9
end!
代码测试:
1.以“utf8”编码读取
dir_path = "../output"
file_name = "test.txt"
fp = open(dir_path + "/" + file_name, "r",encoding='utf8')
print("当前文件指针位置 : ", fp.tell())
str = fp.read(18) # 见说明1
print("fp.read(18)读取到的数据 : ", str)
print("当前文件位置 : ", fp.tell()) # 见说明2
fp.seek(9,0) # 见说明3
print("fp.seek(9,0),当前文件指针位置 : ", fp.tell())
str=fp.readline() # 见说明4
print("fp.readline()读取到的数据 : ", str)
print("当前文件指针位置 : ", fp.tell())
输出:
说明:
- 说明1:
fp.read(18)
读取得到的字符串为这是第一行数据\nabcdefghij
,加上换行一共18个字符,说明该函数对每个中文、英文字符和换行的长度都视为1。 - 说明2:
print("当前文件位置 : ", fp.tell())
改行代码执行后,指针位置在33
,计算方法:7个中文字符,占7×3=21个偏移量,\n
在读取后是\r\n
占2个偏移量,abcdefghij
占10个偏移量,共35个偏移量。 - 说明3:
fp.seek(9,0)
表示指针又从文件头开始,因为utf8编码下每个中文字符占3个偏移量,9个偏移量就是3个中文字符之后。 - 说明4:
fp.readline()
从当前指针位置也就是第一行的第三个字符开始,读取一整行,包括换行符,得到一行数据\n
,然后文件指针总停留在下一行开头 - 另外,
fp.readlines(size)
也是从从当前指针位置开始读取,以列表返回,可以自行尝试
2.同样的测试文件和代码,只是以二进制读取
dir_path = "../output"
file_name = "test.txt"
fp = open(dir_path + "/" + file_name, "rb") #改变为二进制读取
print("当前文件指针位置 : ", fp.tell())
str = fp.read(18) # 见说明
print("fp.read(18)读取到的数据 : ", str)
print("当前文件位置 : ", fp.tell())
fp.seek(9,0)
print("fp.seek(9,0),当前文件指针位置 : ", fp.tell())
str=fp.readline()
print("fp.readline()读取到的数据 : ", str)
print("当前文件指针位置 : ", fp.tell())
输出:
说明:utf8编码后以二进制读取,每个中文代表长度3,read(3)
已经不再是读取3个中(英)文字符,而是3个8位的16进制数了。举个例子,看输出的第二行:\xe8\xbf\x99
这三个表示了3个字节,一个字节是8位的16进制数,所以tell()
说指的偏移量其实就是内存地址的指针偏移,1个偏移量就是1个字节大小。
其它函数根据上面的说明可以自行尝试,重点部分已经详细说明了,原理的话至今还不太懂,关于中文字符的编码,所以欢迎大佬指点菜鸟!