文件操作

  • 按数据的组织形式,可以把文件分为文本文件和二进制文件

文本文件

  • 文本文件存储的是常规字符串,由若干文本行组成,通常每行以换行符‘\n’结尾
  • 常规字符串是指记事本之类的文本编辑器能正常显示、编辑并且人类能够直接阅读和理解的字符串,如英文字母,数字字符串

二进制文件

  • 常见如图形图像文件、音频文件、可执行文件、资源文件、各种数据库文件、各类office文件等都属于二进制文件
  • 二进制文件把信息以字节串进行存储,无法用记事本或其他普通字处理软件直接进行编辑,通常也无法直接阅读和理解,需要使用正确的软件进行解码反序列化之后才能正确的读取、显示、修改或执行

文件操作

  • 无论是文本文件还是二进制文件,操作流程基本都是一致的
  • 首先打开文件并创建文件对象,然后通过该对象对文件内容进行读取、写入、删除、修改等操作

内置函数open()

  • Python内置函数open()可以用指定模式打开指定文件并创建文件对象,该函数完整的用法如下,由于很多参数都有默认值,在使用时只需要给特定的参数传值即可
open(file,mode='r',buffering=-1,encoding=None,errors=None,newline=None,closed=True,opener=None)

内置函数open()的主要参数含义:

  • 参数file指定要打开或创建的文件名称,如果改文件不在当前目录中,可以使用相对路径或绝对路径,为了减少路径中分隔符的输入,可以使用原始字符串
  • 参数mode指定打开文件后的处理方式,默认为“文本只读模式”以不同方式打开文件时,文件指针的初始位置略有不同,以“只读”“只写”模式打开时文件指针的初始位置是文件头,以“追加”模式打开时文件指针的初始位置为文件尾
模式说明
r读模式(默认模式,可以省略),如果文件不存在则抛出异常
w写模式,如果文件已存在,先清空原有内容
x写模式,创建新文件,如果文件已存在则抛出异常
a追加模式,不覆盖文件中原有内容
b二进制模式(可与其他模式组合使用),使用二进制模式打开文件时不允许指定encoding参数
t文件模式(默认模式,可省略)
+读、写模式(可与其他模式组合使用)
  • 如果执行正常,open()函数返回一个可迭代的文件对象,通过该文件对象可以对文件进行读写操作,如果指定文件不存在、访问权限不够、磁盘空间不够或其他原因导致创建文件抛出异常
  • 对文件内容操作完成胡,一定要关闭文件对象,这样才能保证所做的任何修改都被保存到文件中
  • 需要注意的是,即便写了关闭文件的代码,也无法保证文件一定能够正常关闭。若是关闭之前发生错误导致程序崩溃,这时文件就无法正常关闭。with关键字,可以完全避免这个问题

上下文管理语句with

  • 在实际开发中,读写文件应优先考虑使用上下文管理语句with,关键字with可以自动管理资源,不论因为什么原因跳出with块,总能保证文件被正确关闭
  • 可以在代码块执行完毕后自动还原进入该代码块时的上下文,常用于文件操作、数据库连接、网络通信连接、多线程与多进程同步时的锁对象管理场合。
  • 用于文件内容读写时,with语句用法如下:
with open(filename,mode,encoding) as fp:
#这里通过文件对象fp读写文件内容的语句
  • 上下文管理语句with还支持下面的用法,进一步简化代码:
with open('test.txt','r')as src,open('test_new.txt','w')as dst:
         dst.write(src.read())

文件对象属性与常用方法

  • 如果执行正常,open()函数返回一个可迭代的文件对象,通过该文件对象可以对文件进行读写操作
  • 常用属性
属性说明
buffer返回当前文件的缓冲区对象
closed判断文件是否关闭,若文件以关闭则返回True
fileno文件号,一般不需要太关心这个数字
mode返回文件的打开模式
name返回文件的名称
  • 文件读写操作相关的函数都会自动改变文件指针的位置
  • 以读模式打开一个文本文件,读取10个字符,会自动把文件指针移动到第11个字符的位置,再次读取字符的时候总是从文件指针的当前位置开始,写入文件的操作函数也具有相同的特点
方法功能说明
close()把缓冲区的内容写入文件,同时关闭文件,并释放文件对象
flush()把缓冲区的内容写入文件,但不关闭文件
read([size])从文本文件中读取size个字节(Python 2.x)或字符(Python3.x)的内容作为结果返回,或从二进制文件中读取指定数量的字节并返回,如果省略size则表示读取所有内容
readline()从文本文件中读取一行内容作为结果返回
seek(offset[,whence])把文件指针移动到新的位置,offset表示相对于whence的位置。whence为0表示从文件头开始计算,whence为1表示从当前位置开始计算,whence为2表示从文件尾开始计算,默认为0
seekable()测试当前文件是否支持随机访问,如果文件不支持随机访问,则调用方法seek()、tell()和truncate()时会抛出异常
tell()返回文件指针的当前位置
write(s)把字符串s的内容写入文件
writelines(s)把字符串列表写入文本文件,不添加换行符

文本文件内容操作

s="hello world\n文本文件的读取方法\n文本文件的写入方法"

#练习一:将字符串写入文本文件,然后再读取并输出
print("练习一".center(20,'*'))
with open('sample.txt','w') as fp: #默认使用CP936编码
    fp.write(s)
with open('sample.txt') as fp:
    print(fp.read())
fp.close()

********练习一*********
hello world
#练习二:将一个CP936编码格式的文本文件中的内容全部复制到另一个使用UTF-8编码的文本文件中
print("练习二".center(20,'*'))
def fileCopy(src,dst,srcEncoding,dstEncoding):
    with open(src,'r',encoding=srcEncoding) as srcfp:
        with open(dst,'w',encoding=dstEncoding) as dstfp:
            dstfp.write(srcfp.read())
            dstfp.close()
            srcfp.close()

fileCopy('sample.txt','sample_new.txt','cp936','utf-8')
#练习三:遍历并输出文本文件的所有内容
print("练习三".center(20,'*'))
with open('sample.txt') as fp1:
    for line in fp1:
        print(line)
    fp1.close()


********练习三*********
hello world

文本文件的读取方法

文本文件的写入方法
#练习四:假设已有一个文本文件sample.txt,将其中的第13、14两个字符修改为测试
print("练习四".center(20,'*'))
with open('sample.txt','r+') as fp2:
    fp2.seek(13)
    fp2.write("测试")
    fp2.close()

#练习五:假设文件data.txt中有若干整数,所有整数之间使用英文逗号分隔,编写程序读取所有整数,将其按升序排序后再写入文本文件data_asc.txt中
print("练习五".center(20,'*'))
with open('data.txt','r') as fp3:
    data=fp3.readlines() #读取所有行
data=[line.strip() for line in data] #删除每行两侧的空白字符
data=','.join(data) #合并所有行
data=data.split(',') #分隔得到所有数字字符串
data=[int(i) for i in data] #转换为数字
data.sort() #升序排列
data=','.join(map(str,data)) #将结果转为字符串
with open('data_asc.txt','w') as fp4: #将结果写入文件
    fp4.write(data) 
    
#练习六:统计文本文件中最长行的长度和该行的内容
print("练习六".center(20,'*'))
with open('sample.txt') as fp5:
    result=[0,'']
    for line in fp5:
        t=len(line)
        if t>result[0]:
            result=[t,line]
print(result)

********练习六*********
[12, 'hello world\n']

二进制文件操作

  • 所谓序列化,简单的说就是把内存中的数据在不丢失其类型信息的情况下转成二进制形式的过程,对象序列化后的数据经过正确的反序列化过程应该能够准确无误地恢复为原来的对象
  • Python中常用的序列化模块有struct、pickle、shelve、marshal

使用pickle模块读写二进制文件

  • dumps()返回对象序列化后的字节串形式
  • loads()函数用来把序列化的字节串反序列化得到原始数据
import pickle

i=130000
a=99.056
s='你好 123'
lst=[[1,2,3],[2,3,4],[4,5,6]]
tu=(-5,10,8)
coll={4,5,6}
data=(i,a,s,lst,tu,coll)

with open('sample_pickle.dat','wb') as f:
    try:
        pickle.dump(len(data),f) #要序列化的对象个数
        for item in data:
            pickle.dump(item,f) #序列化数据并写入文件
    except:
        print('写文件异常')
with open('sample_pickle.dat','rb') as f:
    n=pickle.load(f) #读出文件中的数据个数
    for i in range(n):
        x=pickle.load(f) #读取并反序列化每个数据
        print(x)


130000
99.056
你好 123
[[1, 2, 3], [2, 3, 4], [4, 5, 6]]
(-5, 10, 8)
{4, 5, 6}

使用struct模块读写二进制文件

import struct

n=130000
x=99.056
b=True
s='al@我'
sn=struct.pack('if?',n,x,b) #序列化,i表示整数,f表示实数,?表示逻辑值

with open('sample_struct.dat','wb') as f:
    f.write(sn)
    f.write(s.encode()) #字符串需要编码为字节串再写入文件
with open('sample_struct.dat','rb') as f:
    sn=f.read(9)
    tu=struct.unpack('if?',sn) #使用指定格式反序列化
    n,x,b1=tu
    print('n=',n,'x=',x,'b1=',b1)
    s=f.read(9)
    s=s.decode() #字符串解码
    print('s=',s)


n= 130000 x= 99.05599975585938 b1= True
s= al@我

在上面的代码中,首先读取9个字节然后进行反序列化,在读取9个字节并解码为字符串。后者之所以是9个字节是因为字符串的encode()方法默认使用UTF-8编码格式,使用3个字节表示一个中文符号,使用一个字节表示英文符号。而前者是9个字节跟struct模块序列化规则有关,每个类型的数据序列化时占用的字节数是固定的。

使用shelve模块操作二进制文件

  • 标准库shelve提供了二进制文件操作的功能,可以向字典复制一样来写入二进制文件,也可以像字典一样读取二进制文件
import shelve
zhangsan={'age':3,'sex':'Male','address':'SD'}
lisi={'age':4,'sex':'Male','qq':'123456','tel':'7689797'}
with shelve.open('shelve_test.dat') as fp:
    fp['zhangsan']=zhangsan #以字典形式把数据写入文件
    fp['lisi']=lisi
    for i in range(5):
        fp[str(i)]=str(i)
with shelve.open('shelve_test.dat') as fp:
    print(fp['zhangsan']) #读取并显示内容
    print(fp['zhangsan']['age'])
    print(fp['lisi']['qq'])
    print(fp['3'])

{'age': 3, 'sex': 'Male', 'address': 'SD'}
3
123456
3

使用扩展库openpyxl读写Excel2007以及更高版本的文件


import openpyxl
from openpyxl import Workbook

fn=r'C:\Users\***\Desktop\test.xlsx' #文件名
wb=Workbook() #创建工作簿
ws=wb.create_sheet(title='你好 世界') #创建工作表
ws['A1']='这是第一个单元格' #单元格赋值
ws['B1']=3.1415926
wb.save(fn) #保存Excle文件

wb=openpyxl.load_workbook(fn) #打开已有的Excel文件
ws=wb.worksheets[1] #打开指定索引的工作表
print(ws['A1'].value) #读取并输出指定单元格的值
ws.append([1,2,3,4,5]) #添加一行数据
ws.merge_cells('F2:F3') #合并单元格
ws['F2']="=sum(A2:E2)" #写入公式
for r in range(10,15):
    for c in range(3,8):
        _=ws.cell(row=r,column=c,value=r*c) #写入单元格数据
wb.save(fn)

这是第一个单元格

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值