本文通过针对不同应用场景及其解决方案的方式,总结了Python中对文件与IO的一些相关知识,具体如下:
1.读写文本数据
应用场景:需要读取不同编码的文本数据,如ASCII,UTF-8,UTF-16等
解决方案:使用带有rt模式的open()函数
#读写文本文件
#1 single string
with open('somefile.txt') as f:
data=f.read
#2 迭代所有行
with open('somefile.txt','rt') as f:
for line in f:
print(line)
#3 重定向输出到文件
with open('somefile.txt','wt') as f:
print(line1,file=f)
print(line2,file=f)
#指定编码方式
with open('somefile.txt','rt',encoding='utf-8') as f:
for line in f:
print(line)
2.读写字节数据
应用场景:需要读取二进制文件,如图片、声音文件等
解决方案:使用带有rb、wb模式的open()函数
示例1
with open('somefile.bin','rb') as f:
data=f.read(16)
text=data.decode('utf-8')
with open('somefile.bin','wb') as f:
text='helloword'
f.write(text.encode('utf-8'))
示例2 数组和c结构体直接写入
import array
nums=array.array('i',[1,2,3,4])
with open('data.bin','wb') as f:
f.write(nums)
3.读写压缩文件
应用场景:读写一个gzip或bz2格式的压缩文件
解决方案:使用gzip和bz2模块的open()函数
读:
import gzip
with gzip.open('somefile.gz','rt') as f:
text=f.read()
import bz2
with bz2.open('somefile.bz2','rt') as f:
text=f.read()
写:
import gzip
with gzip.open('somefile.gz','wt') as f:
f.write(text)
import bz2
with bz2.open('somefile.bz2','wt') as f:
f.write(text)
4.读取二进制数据到可变缓冲区
应用场景:需要直接读取二进制数据到一个缓冲区,而不需要做任何的中间复制操作
解决方案:使用文件对象的readinto()方法
示例
import os.path
def read_into_buffer(filename):
buf=bytearray(os.path.getsize(filename))
with open(filename,'rb') as f:
f.readinto(buf)
return buf
#test case
with open('sample.bin','wb') as f:
f.write(b'helloworld')
buf=read_into_buffer('sample.bin')
buf
buf[0:5]=b'hahah'
buf
with open('newsample.bin','wb') as f:
f.write(buf)
5.文件路径名 的操作
应用场景:需要使用路径名来获取问文件名、目录名、绝对路径等
解决方案:使用os.path模块中的函数来操作路径名
示例
import os
path='/home/dw/ls-output.txt'
os.path.basename(path)
os.path.dirname(path)
os.path.join('tmp','data',os.path.basename(path))
path='~/ls-output.txt'
os.path.expanduser(path)
os.path.splitext(path)
6.增加或改变已经打开文件的编码
应用场景:想在不关闭一个已打开文件的前提下增加或者改变其Unicode编码
解决方案:使用io.TextIOWrapper()对象包装它
示例
import urllib.request
import io
u=urllib.reques.urlopen('http://www.python.ory')
f=io.TextIOWrapper(u,encoding='utf-8')
text=f.read()
import sys
sys.stdout.encoding
#detach移除已存在的文本编码层,使用新的编码方式代替
sys.stdout=io.TextIOWrapper(sys.stdout.detach(),encoding='latin-1')
sys.stdout.encoding
7.创建临时文件或文件夹
应用场景:需要在程序执行时创建一个临时文件或目录,使用完之后自动销毁
解决方案:使用tempfile.TemporaryFile
示例1 创建临时文件
from tempfile import TemporaryFile
#文本模式为w+t,二进制模式为w+b
with TemporaryFile('w+t') as f:
f.write('helloworl\n')
f.write('testing\n')
#回溯并读取数据
f.seek(0)
data=f.read()
#临时文件自动被销毁
示例2创建临时目录
from tempfile import TemporaryDirectory
with TemporaryDirectory() as dirname:
print('dirname is :',dirname)
#此处可以使用上述创建的目录
#目录下的所有内容会自动销毁
8.序列化Python对象
应用场景:需要将一个Python对象序列化为一个字节流,以便将其保存到一个文件或存储到数据库或者通过网络传输它
解决方案:使用pickle模块
示例1
import pickle
data=...
f=open('somefile','wb')
pickle.dump(data,f)
#将对象转存为一个字符串
s=pickle.dumps(data)
#从字节流中恢复一个对象
f=open('somefile','rb')
data=pickle.load(f)
data=pickle.load(s)
示例2
class Countdown:
def __init__(self,n):
self.n=n
self.thr=threading.Thread(target=self.run)
self.thr.daemon=True
self.thr.start()
def run(self):
while self.n>0:
print('t-minus',self.n)
self.n -=1
time.sleep(5)
def __getstate__(self):
return self.n
def __getstate__(self,n):
self.__init__(n)
#test case
import countdown
c=countdown.Countdown(30)
t-minus 30
f=open('cstate.p','wb')
import pickle
pickle.dump(c,f)
f.close()
#退出python解析器并重启后再执行
f=open('cstate.p','rb')
pickle.load(f)