pythonIO流中的seek()和read()函数详解

说明

  • 内容基于*《Python程序设计(第三版 董付国 编著)》*中的文本文件操作案例精选。

源代码

  • 需要注意的是,文中采用IDLE运行代码,为了便于理解,故迁移至pycharm
s = '中国山东烟台SDIBT'
fp = open(r'test.txt', 'w')
fp.write(s)
fp.close()

fp = open(r'test.txt', 'r')
print(fp.read(3))	# 输出结果:中国山
print(fp.seek(2))	# 输出结果:2(传入的参数多少即返回多少)
print(fp.read(1))   # 输出结果:国
print(fp.seek(13))	# 输出结果:13(传入的参数多少即返回多少)
print(fp.read(1))	# 输出结果:D
print(fp.seek(15))	# 输出结果:15(传入的参数多少即返回多少)
print(fp.read(1))	# 输出结果:B
print(fp.seek(3))	# 输出结果:3(传入的参数多少即返回多少)
print(fp.read(1))	# 报错: UnicodeDecodeError: 'gbk' codec can't decode byte 0xfa in position 0: illegal multibyte sequence

# read([size]) # 从文件中读取size字节(二进制文件)或字符(文本文件)的内容作为结果返回,如果省略size,则表示一次性读取所有内容
# seek()    # 将文件指针定位到文件中指定字节的位置。读取时遇到无法解码的字符会抛出异常。

# for i in range(1, 10):
#     fp.seek(13)
#     print(fp.read(1))

函数说明

  • seek(num) :将文件指针定位到文件中指定字节的位置。读取时遇到无法解码的字符会抛出异常。 针对于这个函数,我们需要明确的是:其移动单位字节,不是字符例如: 在一个同时含有中英文文本文件中,其采用的编码是’gbk’,那么就要注意,一个中文字一个字符,但是它占两个字节一个英文字也是一个字符,但是它占一个字节。如果将文件指针定位到一个中文的中间字节位置,肯定是无法解码的,因而会抛出异常。
  • read([size]) :从文件中读取size字节(二进制文件)或字符(文本文件)的内容作为结果返回,如果省略size,则表示一次性读取所有内容。针对于这个函数,我们需要注意的是:当读取的文件类型不同时,size的单位不一样二进制文件的读取单位字节文本文件的读取单位字符。并且在。每一次读取成功后文件指针自动向后移动

详细解析

# 此处定义了s变量,是一个中英文混合的字符串
s = '中国山东烟台SDIBT'
"""
	首先明确一下这里的s字符串总共只有11个字符,书中的'台'和'S'之间
	有段空隙,容易误以为有一个空格,实际上是没有的
	在这里,我们可以通过插入代码查看字符串s的所占用的字符长度和字节长度
	print('所占用的字符长度:', len(s))
	print('所占用的字节长度:', len(s.encode('gbk')))
"""

# 此处以'w'模式创建一个名为test.txt的文本文件,并将s字符串写入到
# 这个文本文件中,因没有指定编码,默认采用'gbk'格式,这也是为什么
# 我们上面在输出字节长度时采用gbk编码进行编码。
fp = open(r'test.txt', 'w')
fp.write(s)
fp.close()

# 此处以'r'模式打开上方写好的test.txt文本文件
fp = open(r'test.txt', 'r')

"""
	反复强调,此处的test.txt是一个文本文件,参考上面的函数解析,
	可以明确,seek(num)的移动单位是字节,而read([size])的移动单位是字符
	还有一件事:当我们以'r'模式打开test.txt文本文件后,没有特别指定
	文件指针的位置,因此当前位置为0,也就是开头。这里我们增加一个
	变量p表示文件指针的位置的数值。
	还有一件事:为了直观,我会在如下用&表示文件指针(即光标)的位置。
"""
# 读取前:p = 0  即 &中国山东烟台SDIBT
# 读取三个字符
print(fp.read(3))	# 输出结果:中国山
# 读取后:由于这三个字符是中文,一个中文2个字节,总共6个字节。p = 0 + 6 = 6  即 中国山&东烟台SDIBT

# 将文件指针移到第2字节的位置
fp.seek(2)

# 读取前:p = 2	即 中&国山东烟台SDIBT
# 读取一个字符
print(fp.read(1))   # 输出结果:国
# 读取后:由于这个字符是中文,一个中文2个字节,总共2个字节。p = 2 + 2 = 4 即 中国&山东烟台SDIBT

# 将文件指针移到第13字节的位置
fp.seek(13)

# 读取前:p = 13	 即 中国山东烟台S&DIBT
# 读取一个字符
print(fp.read(1))	# 输出结果:D
# 读取后:由于这个字符是英文,一个中文1个字节,总共1个字节。p = 13 + 1 = 14	即 中国山东烟台SD&IBT

# 将文件指针移到第15字节的位置
fp.seek(15)

# 读取前:p = 15	 即 中国山东烟台SDI&BT
# 读取一个字符
print(fp.read(1))	# 输出结果:B
# 读取后:由于这个字符是英文,一个中文1个字节,总共1个字节。p = 15 + 1 = 16	即 中国山东烟台SDIB&T

# 将文件指针移到第3字节的位置
fp.seek(3)

# 读取前:p = 3,即位于'国'的中间字节位置,往下读取的内容不完整
# 因此执行这个会抛出无法解码的异常
print(fp.read(1))

拓展

  • 针对报错信息:UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xfa in position 0: illegal multibyte sequence的理解
  • 当出现这个报错信息时,有两种情况,其一是由于读取文件采用的编码与文件原有的编码不匹配。比如一份文件原本是采用utf-8编码写入,但是却采用gbk读取,那么肯定无法读取。解决的方式就是以正确的编码格式读取就好了。其二就是上面遇到的情况,文件指针的位置不正确,导致无法正常读取。

关于在IDLE中不需要加print也能看到输出

  • IDLE是一种交互式的python解释器,能够自动将返回值进行输出

你可能感兴趣的:(python)