引言
文件是长久保存信息并允许重复和反复修改的重要方式,同时也是信息交换的重要途径。
- 文本文件
扩展名为txt,log,ini的文件都属于文本文件,可以使用字处理软件如gredit、记事本、UltraEdit等进行编辑。
- 二进制文件
常见的如图形图像文件、音视频文件、可执行文件、资源文件、各种数据库文件、各类Office文件等都属于二进制文件。二进制文件把信息以字节串(bytes)进行存储,无法使用记事本或其他普通字处理软件直接进行编辑,通常也无法直接阅读和理解,需要使用正确的软件进行解码或反序列化之后才能正确的读取、显示、修改或执行。
文件操作基本知识
首先打开文件并创建文件对象,然后通过该文件对象对文件内容进行读取、写入、删除、修改等操作,最后关闭并保存文件内容。
内置函数open():open(file,mode='r',buffering = -1,encoding = None,errors = None,newlines = None,closefd = True,opener = None)
注意:如果执行正常,open()函数返回一个人可迭代的文件对象,通过该文件对象可以对文件进行读写操作,如果指定文件不存在、访问权限不够、磁盘空间不够或其他原因导致创建文件对象失败则抛出异常,f1 = open('file1.txt','r'),f2 = open('file2.txt','2').
当对文件内容操作完以后,一定亚欧鞍鼻文件对象,这样才能保证多做的任何修改都被保存到文件当中。
f1.close()
上下文管理语句with: 在实际开发中,读写文件应优先考虑使用上下文管理语句with,关键字with可以自动管理资源,不论因为什么原因跳出with块,总能保证文件被正常关闭。
with open(filename,mode,encoding) as fp:
#这里通过文件对象fp读写文件内容的语句
另外,上下文管理语句with还支持下面的用法,进一步简化了代码的编写。
with open('text.txt','r') as src,open('text_new.txt','w') as dst:
dst.write(src.read()) #类似于复制
- 使用pickle模块读写二进制文件
标准化pickle提供的dump()方法(protocol参数为True时可以实现压缩的效果)将数据进行序列化并写入文件,load()方法读取二进制文件内容并进行反序列化,还原为原来的信息。
import pickle
i = 13000000
a = 99.056
s = '中国人民 123abc'
lst = [[1,2,3],[4,5,6],[7,8,9]]
tu = (-5,10,8)
coll = {4,5,6}
dic = {'a':'apple','b':'banana','g':'grape','o':'orange'}
data = (i,a,s,lst,tu,coll,dic)
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)
- 使用struct模块读写二进制文件
使用struct模块时需要使用pack()方法把对象按指定的格式进行序列化,然后使用文件对象的write()方法将序列化的结果写入二进制文件;读取时需要使用文件对象的read()方法读取二进制文件的内容,然后使用struct模块unpack()方法反序列化得到原来的信息。
import struct
n = 1300000000
x = 996.45
b = True
s = 'a1@中国'
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)
- 使用shelve模块操作二进制文件
Python标准库shelve也提供了二进制文件文件操作的功能,可以向字典赋值一样来写入人进制文件,也可以像字典一样读取二进制文件。
- 其他常见类型二进制操作文件
Excel操作
from xlwt import *
import xlrd
book = Workbook() #创建新的excel文件
sheet1 = book.add_sheet("First") #添加新的worksheet
a1 = Alignment()
a1.horz = Alignment.HORZ_CENTER #对齐方式
a1.vert = Alignment.VERT_CENTER
borders = Borders()
borders.bottom = Borders.THICK #边框样式
style = XFStyle()
style.alignment = a1
Style.borders = borders
row = sheet1.row(0) #获取第0行
row.write(0,'test',style = style) #写入单元格
row = sheet1.row(1)
for i in range(5):
row.write(i,i,style = style)#写入数字
row.write(5,'=SUM(A2:E2)',style = style)#写入公式
book.save(r'D:\test.xls') #保存文件
book = xlrd.open_workbook(r'D:\test.xls')
sheet1 = book.sheet_by_name('First')
row = sheet1.row(0)
print(row[0].value)
print(sheet1.row(1)[2].value)
excel操作2
import openpyxl
from openpyxl import Workbook
fn = r'D:\test.xlsx' #文件名
wb = Workbook() #创建工作簿
ws = wb.create_sheet(title = '你好,世界') #创建工作表
ws['A1'] = '这是第一个单元格' #单元格赋值
ws['B1'] = 3.1415926
wb.save(fn) #保存Excel文件
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)
## 表格随机数据的生成
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 23 22:11:58 2021
@author: 86176
"""
import openpyxl
from openpyxl import Workbook
import random
#生成随机数据
def generateRandomInformation(filename):
workbook = Workbook()
worksheet = workbook.worksheets[0]
worksheet.append(['姓名','课程','成绩'])
#中文名字中的第一、第二、第三个字
first = '赵钱孙李'
middle = '伟昀琛东'
last = '坤艳志'
subjects = ('语文','数学','英语')
for i in range(200):
line = []
r = random.randint(1,100)
name = random.choice(first)
# 按一定概率生成只有两个字的中文名字
if r > 50:
name = name + random.choice(middle)
name = name + random.choice(last)
# 依次生成姓名、课程名称和成绩
line.append(name)
line.append(random.choice(subjects))
line.append(random.randint(0,100))
worksheet.append(line)
# 保存数据,生成Excel2007格式的文件
workbook.save(filename)
def getResult(oldfile,newfile):
# 用于存放结果数据的字典
result = dict()
#打开原始数据
workbook = openpyxl.load_workbook(oldfile)
worksheet = workbook.worksheets[0]
# 遍历原始数据
for row in worksheet.rows:
if row[0].value == '姓名':
continue
# 姓名、课程名称、本次成绩
name,subject,grade = row[0].value,row[1].value,row[2].value
# 获取当前姓名对应的课程名称和成绩信息
# 如果result 字典中不包含,则返回空字典
t = result.get(name,{})
# 获取当前学生当前课程的成绩,若不存在,返回0
f = t.get(subject,0)
# 只保留该学生该课程的最高成绩
if grade > f:
t[subject] = grade
result[name] = t
workbook1 = Workbook()
worksheet1 = workbook.worksheets[0]
worksheet1.append(['姓名','课程','成绩'])
# 将result字典中的结果数据写入Excel文件
for name,t in result.items():
print(name,t)
for subject,grade in t.items():
worksheet1.append([name,subject,grade])
workbook1.save(newfile)
if __name__ == '__main__':
oldfile = r'D:\test1.xlsx'
newfile = r'D:\result.xlsx'
generateRandomInformation(oldfile)
getResult(oldfile,newfile)
# txt文件转xlsx文件
from openpyxl import Workbook
def main(txtFileName):
new_XlsxFileName = txtFileName[:-3] + 'xlsx'
wb = Workbook()
ws = wb.worksheets[0]
with open(txtFileName) as fp:
for line in fp:
line = line.strip().split(',')
ws.append(line)
wb.save(new_XlsxFileName)
main('test.txt')
# 使用Python标准库tarfile把当前文件夹中所有.py文件压缩为gzip格式的压缩文件,然后在解压缩到指定文件夹中。
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 25 21:17:41 2021
@author: 86176
"""
import os
import tarfile
with tarfile.open('sample.tar','w:gz') as tar:
for name in [f for f in os.listdir('.') if f.endswith('.py')]:
tar.add(name)
with tarfile.open('sample.tar','r:gz') as tar:
tar.extractall(path = 'sample')