python中的文件IO之一
python 中有三种I/O, 分别是text I/O, binary I/O, raw I/O,
属于任意一种类型所对应的的对象都叫做file object, 也叫做stream, file-like object.
创建一个file object的通用方法是用open函数, 可以用来创建text I/O和binary I/O.
open函数的参数mode代表对文件操作的类型, 按照文件内容有二进制和纯文本,
按照操作类型可以分为以下几种, 摘自官方文档
- 'r' open for reading (default)
- 'w' open for writing, truncating the file first
- 'x' create a new file and open it for writing
- 'a' open for writing, appending to the end of the file if it exists
- 'b' binary mode
- 't' text mode (default)
- '+' open a disk file for updating (reading and writing)
Text I/O¶
%%writefile myfile.txt
"这是一个测试的文本文件"
"hello can you hear me"
import io
# create a text stream
file1 = open('myfile.txt', 'r', encoding='utf8')
# create a in memory text stream
file2 = io.StringIO('texts stored in memory')
assert isinstance(file1, io.TextIOBase)
assert isinstance(file2, io.TextIOBase)
text stream对象的基类是TextIOBase, 我们重点关注以下几个方法
-
read(size=-1)
按照size读取文本内容, 到达文件末尾时停止, size为负数或None时读取全部内容 -
readline(size=-1)
按照size读取文本内容, 遇到换行符时或到达文件末尾时停止,
size为负数或None或者读取一行全部内容, 如果已经在文件末尾, 返回空字符串 -
seek(offset, whence=SEEK_SET)
改变文件指针的位置, 默认从0开始移动, offset是移动的偏移量, offset是指字节的大小, 一个中文字符是三个字节.
whence可以是0, 1, 2代表从开始位置, 当前位置, 结束位置, 只有whence=0的时候, offset才可以有0以外的值 -
tell()
返回当前的文件指针位置 -
write(s)
写入文本
f = open('myfile.txt', 'r', encoding='utf8')
print("现在文件指针位置在%d" % f.tell())
print("让我们从开始位置读%d个字符: '%s'" % (10, f.read(10)))
print("现在文件指针位置在%d" % f.tell())
print("再从位置%d开始向后读取%d个字符: '%s'" % (f.tell(), 5, f.read(5)))
print("现在文件指针位置在%d" % f.tell())
print("最后从位置%d读取一行, size为%d: '%s'" % (f.tell(), 10, f.readline()))
print("现在文件指针位置在%d" % f.tell())
print("看看现在还剩下什么: '%s'" % f.read())
f.close()
通过上面的例子可以看出:
- 每次使用f.read() 或者 f.readline() 之后文件的指针都会移动, 具体视size的大小而定
- f.read()或者f.readline() 每次都是从文件指针的位置开始向后读取size大小的字符
- f.read(size) size指的是字符的大小, 而不是每个字所占的字节的大小
- f.tell() 返回的位置是按照字节大小来计算的, 一个中文占三个字节, 一个字母占一个字节
- 换行符也算一个字符, readline和read 返回的行文本包含了行尾的换行符
- 因为文件指针一直在移动, 所以无法再读取已经读取过的内容, 除非手动移动指针的位置
下面来试试seek方法
f = open('myfile.txt', 'r', encoding='utf8')
print(f.read(1).encode('utf8'))
print("现在文件指针位置在%d" % f.tell())
f.seek(0)
print("现在文件指针位置在%d" % f.tell())
f.seek(1)
print("现在文件指针位置在%d" % f.tell())
try:
f.read(1)
except UnicodeDecodeError:
print("编码错误")
前面说过f.tell()返回的位置是按照字节大小来计数, f.seek()也是按照字节数来移动文件指针, 而如果文本中有字符的字节数不为1的话, f.seek()可能会移动到某个字符的中间位置, 这时就会无法识别当前是什么字符, 这个例子中最后的f.seek(1) 之后指针所在位置的字节是\xbf, 无法与后续的字节构成一个合法的字符, 抛出UnicodeDecodeError.
读完本文, 希望你能够回答以下问题.
- 如何优雅的读写文件
- 如何追加内容到文件的开始
- 如何追加内容到文件的指定行
- 如何优化读写速度
- 操作文件指针
- 使用进程/线程锁确保数据一致性
Comments