Python IO编程

IO编程

读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

open函数

该函数用于文件处理,传入文件路径和标示符。打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。

打开文件的模式有:

  • r ,只读模式【默认,不存在则报错】】
  • w,只写模式【不可读;不存在则创建;存在则清空内容;】
  • x, 只写模式【不可读;不存在则创建,存在则报错】
  • a, 追加模式【可读; 不存在则创建;存在则只追加内容;】

“+” 表示可以同时读写某个文件:

  • r+, 读写【可读,可写】
  • w+,写读【可读,可写】
  • x+ ,写读【可读,可写】
  • a+, 写读【可读,可写】

“b”表示以字节的方式操作:

  • rb 或 r+b
  • wb 或 w+b
  • xb 或 w+b
  • ab 或 a+b

注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型

只读模式

只读,文本文件
f = open("writeFile.txt", "r")
data = f.read()
f.close()
print(data)

read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示。close()方法关闭文件,文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的。

调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。

如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便。

只读,二进制文件
f = open("writeFile.txt", "rb")
data = f.read()
f.close()
print(data)

//结果
b'\xe5\x8e\x89\xe5\xae\xb3\xe5\x93\x88\xe5\x93\x88\xe5\x8e\...

要读取二进制文件,可以用二进制方式打开,读到的内容是十六进制表示的字节。

要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

f = open("writeFile.txt", "r",encoding='gbk')

遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

f = open("writeFile.txt", "r",encoding='gbk',errors='ignore')

只写模式

先清空数据,再写
f2 = open("writeFile.txt", "w")
追加数据,只写
f2 = open("writeFile.txt", "a")
f2.write("sdfsdfsfsfs")
f2.close()

//二进制方式打开
先清空数据,再写
f2 = open("writeFile.txt", "wb")
追加数据,只写
f2 = open("writeFile.txt", "ab")
f2.write(bytes("中国", encoding="utf-8"))
f2.close()

你可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。

读写模式

r+模式的读写:

# 读写,如果有中文,默认会变成gbk编码
# r+ ,末尾追加,指定在最后
f = open("writeFile.txt", "r+", encoding='utf-8')
data = f.read()
# 读或写完数据之后,指定会在最后的位置,指针位置以字节算,tell用来获取指针位置,seek用来改变指定位置
print(f.tell())

f.write("厉害")
print(f.tell())

data = f.read()
print(f.tell())

f.write("哈哈")
print(f.tell())

f.close()
print(data)

//结果,120,126,126,132

w+模式的读写:

# 写读,如果有中文,默认会变成gbk编码
# w+ ,先清空,在写之后,才可以读

f = open("writeFile.txt", "w+", encoding='utf-8')
#此时内容已清空,所以读到的内容为空,指针为0
data = f.read()
# 读或写完数据之后,指定会在最后的位置,指针位置以字节算,tell用来获取指针位置,seek用来改变指定位置
print(f.tell())

f.write("厉害")
print(f.tell())

data = f.read()
print(f.tell())

f.write("哈哈")
print(f.tell())

//结果,0,6,6,12

a+模式的读写:

# 追加,如果有中文,默认会变成gbk编码
# a+ ,打开文件时就将指针移到最后的位置
f = open("writeFile.txt", "a+", encoding='utf-8')
data = f.read()
# 读或写完数据之后,指定会在最后的位置,指针位置以字节算,tell用来获取指针位置,seek用来改变指定位置
print(f.tell())

f.write("厉害")
print(f.tell())

data = f.read()
print(f.tell())

f.write("哈哈")
print(f.tell())

# 此时指针是最后,要想读所有数据,把指针放到0位置,再读一次,就有数据了
f.seek(0)
data = f.read()
f.close()
print(data)

//结果,12,18,18,24,厉害哈哈

IO的一些方法

刷新文件内部缓冲区
f.flush()
读取一行数据
f.readline()
一次读取所有内容并按行返回list
f.readlines()
截取当前指针前面的数据,指针后面的数据全部删除
f.truncate()
读取数据,可以指定读取的字节数量
f.read()

注意 ,f是可以遍历的,每个元素是一行数据
for line in f:
    print(line)

可以用with 关键字来避免每次都调用close
with open("writeFile.txt", "r", encoding='utf-8') as f:
    print(f.readline())

可以同时打开两个文件,下面的例子是复制文件内容到一个新的文件里面
with open("writeFile.txt", "r", encoding='utf-8') as f, open("copyFile.txt", "w", encoding='utf-8') as f2:
    for data in f:
        f2.write(data)