一、概述
数据的存储可以使用数据库,也可以使用文件。
数据库保持了数据的完整性和关联性,且使用数据更安全、可靠。使用文件存储数据则非常简单、易用,不必安装数据库管理系统等运行环境。
文件通常用于存储应用软件的参数或临时性数据,是一个命名的比特集合,存储在硬盘、U盘、闪存条等辅助存储设备中。
文件分为两类:文本文件和二进制文件。 Python提供了os、os.path、shutil等模块处理文件。
文本文件的特点:
基本是字符串。Python源代码文件和HTML文件等都属于文本文件。
可使用任何文本编辑器进行编辑,对人来说相对容易阅读和修改。
对程序来说,无法直接阅读文本文件。通常,每种文本文件都需要使用相应的分析程序来阅读,例如,Python使用专用分析程序来帮助阅读.py文件,而要阅读HTML文件,需要使用专用于HTML的分析程序。
通常比等价的二进制文件大。需要通过网络发送大型文本文件时,一般要进行压缩(如压缩成zip格式),以提高传输速度和节省磁盘空间。
二进制文件的特点:
通常是人无法直接阅读的,且使用常规的文本编辑器无法查看。在文本编辑器中打开二进制文件时,显示的是一堆乱码。有些类型的二进制文件(如JPEG图像)需要使用特殊查看器显示其内容。
占据的空间通常比等价的文本文件小。
对程序来说,可以直接阅读二进制文件。虽然二进制文件各不相同,但通常无需编写复杂的分析程序来读取它们。
二、文件的常见操作
- 打开文件: 建立磁盘上的文件与程序中的对象相关联 ;通过相关的文件对象获得
- 文件操作: 读取、写入 复制、删除 ;定位; 其他:追加、计算等
- 关闭文件 :切断文件与程序的联系; 写入磁盘,并释放文件缓冲区
1、文件的创建
文件的打开或创建可以使用open函数。该函数可以指定处理模式,设置打开的文件为只读、只写或可读写状态。
格式1: open(file, [mode[, buffering]])—>file object
格式2:with open(file, [mode[, buffering]]) as file object name
- 参数file是被打开的文件名。若文件file不存在,open()将创建该文件,然后再打开该文件。
- 参数mode是指文件的打开模式(默认r)。打开模式如表8-1。
- 参数buffering设置缓存模式。0表示无缓冲;1表示行缓冲;如果大于1则表示缓冲区的大小,,-1(或者任何负数,默认为-1)代表使用默认的缓冲区大小。以字节为单位。
- open()返回1个file对象,file对象可以对文件进行各种操作。
参数 | 描述 |
r | 只读模式,如果文件不存在,返回异常FileNotFoundError,默认值 |
w | 覆盖写模式,文件不存在则创建,存在则完全覆盖 |
x | 创建写模式,文件不存在则创建,存在则返回异常FileExistsError |
a | 追加写模式,文件不存在则创建,存在则在文件最后追加内容 |
t | 文本文件模式,默认值 |
b | 二进制文件模式,可与r/w/x/a/+结合使用 |
+ | 与r/w/x/a一同使用,在原功能基础上增加同时读写功能 |
U | 支持所有的换行符号。如:’\r’、’\n’、’\r\n’ |
file类用于文件管理,可以对文件进行创建、打开、读写、关闭等操作。
文件的处理一般分为三个步骤:
- 创建并打开文件,使用open()函数返回1个file对象。
- 调用file对象的read()、write()等方法处理文件。
- 调用close()关闭文件,释放file对象占用的资源(若使用格式2,可省略此步骤)。
file类的常用属性和方法
属性和方法 | 描述 |
closed | 判断文件是否关闭,如果文件关闭,返回True |
encoding | 显示文件的编码类型 |
mode | 显示文件的打开模式 |
name | 显示文件的名称 |
newlines | 文件使用的换行模式 |
flush() | 将缓冲区的内容写入磁盘 |
close() | 关闭文件 |
read([size]) | 从文件中读取size个字节的内容,作为字符串返回;默认返回包含整个文件内容的一个字符串 |
readline([size]) | 从文件中读取1行,作为字符串返回。若指定size,表示每行每次读取的字节数,依然要读完整行的内容 |
readlines([size]) | 返回值为整个文件内容的列表,每项是以换行符为结尾的一行字符串。若指定size,表示每次读取的字节数 |
属性和方法 | 描述 |
closed | 判断文件是否关闭,如果文件关闭,返回True |
encoding | 显示文件的编码类型 |
mode | 显示文件的打开模式 |
name | 显示文件的名称 |
newlines | 文件使用的换行模式 |
flush() | 将缓冲区的内容写入磁盘 |
close() | 关闭文件 |
read([size]) | 从文件中读取size个字节的内容,作为字符串返回;默认返回包含整个文件内容的一个字符串 |
readline([size]) | 从文件中读取1行,作为字符串返回。若指定size,表示每行每次读取的字节数,依然要读完整行的内容 |
readlines([size]) | 返回值为整个文件内容的列表,每项是以换行符为结尾的一行字符串。若指定size,表示每次读取的字节数 |
2、文件的读取
文件的读取有多种方法,包括: readline() readlines() read()
(1)按行读取方式readline()
readline()每次读取文件中的一行,需要使用永真表达式循环读取文件。但当文件指针移动到文件的末尾时,依然使用readline()读取文件将出现错误。因此程序中需要添加1个判断语句,判断文件指针是否移动到文件的尾部,并且通过该语句中止循环。
(2)多行读取方式
函数readlines()可一次性读取文件中多行数据。例如:readlines(2),可读入两行数据。 使用readlines()读取文件,需要通过循环访问readlines()返回的内容。
(3)一次性读取方式
读取文件最简单的方法是使用read(),read()将从文件中一次性读出所有的内容,并赋值给1个字符串变量。 但这种方式占内存最大。 若read()带有参数,则读入指定字节数。例如,read(5),读入5个字节的数据。
3、文件的写入
从计算机内存向文件写入数据。 文件的写入同样有多种方法,可以使用write()、writelines()方法写入文件。
将字符串写入文件开头:
相比在文件末尾添加字符串,将字符串写入文件开头不那么容易,因为操作系统没有提供这样的支持。 解决的方法是:将文件读取到一个字符串中,将新文本插入到该字符串,再将这个字符串写入原来的文件。
4、文件的删除
删除文件需要使用os模块和os.path模块。
os模块提供了对系统环境、文件、目录等操作系统级的接口函数。
下表列出了os模块常用的文件处理函数。
注意:os模块的open()函数与内置的open()函数的用法不同。
函数 | 描述 |
access(path,mode) | 按照mode指定的权限访问文件 |
chmod(path,mode) | 改变文件的访问权限 |
open*filename,flag[,mode=0o777]) | 按照mode指定的权限打开文件。默认情况下,给所有用户读、写、执行的权限 |
remove(path) | 删除path指定的文件 |
rename(old,new) | 重命名文件或目录。old表示原文件或目录,new表示新文件或目录 |
stat(path) | 返回path指定文件的所有属性 |
fstat(path) | 返回打开的文件的所有属性 |
lseek(fd,pos,how) | 设置文件的当前位置,返回当前位置的字节数 |
startfile(filepath[,operation]) | 起动关联程序打开文件。例如:打开的是一个html文件,将启动IE浏览器 |
tmpfile() | 创建一个临时文件,文件创建在操作系统的临时目录中 |
函数 | 描述 | 函数 | 描述 |
abspath(path) | 返回path所在的绝对路径 | isabs(s) | 测试路径是否绝对路径 |
dirname(p) | 返回目录的路径 | isdir(path) | 判断path指定的是否是目录 |
exists(path) | 判断文件是否存在 | isfile(path) | 判断path指定的是否是文件 |
getatime(filename) | 返回文件的最后访问时间 | split(p) | 对路径进行分隔,并以列表方式返回 |
getctime(filename) | 返回文件的创建时间 | splitext(p) | 从路径中分割文件的扩展名 |
getmtime(filename) | 返回文件的最后修改时间 | splitdrive(p) | 从路径中分割驱动器的名称 |
getsize(filename) | 返回文件的大小 | walk(top,func,arg) | 遍历目录数,与os.walk()功能相同 |
5、文件的复制
file类并没有提供直接复制文件的方法,但可以使用read()、write()方法来实现复制文件的功能。
复制文件的其他方法:
shutil模块是另一个文件、目录的管理接口,提供了一些用于复制文件、目录的函数。
其中,copyfile()函数可以实现文件的复制,move()函数可以实现文件的移动。
copyfile(src, dst)
move(src, dst)
其中,参数src表示源文件的路径,dst表示目标文件的路径,均为字符串类型。
6、文件的重命名
os模块的函数rename()可以对文件或目录进行重命名。 在实际应用中,经常需要将某一类文件修改为另一种类型,即修改文件的后缀名。可以通过函数rename()和字符串查找函数来实现。
7、文件内容的搜索和替换
文件内容的搜索和替换可以使用字符串查找和替换来实现。
8、处理二进制文件
Python中,通常使用pickle模块处理二进制文件。 可以使用pickle.dump将数据结构存储到磁盘,之后再用pickle.load从磁盘获取数据结构。
pickle不能用于读写特殊格式的二进制文件,如各种格式的图像文件。对这种格式的文件,要用专用模块处理(如:PIL库)
三、目录的常见操作
Python的os模块和os.path模块还提供了一些针对目录操作的函数。
1、创建目录和删除目录 os模块提供的常用目录处理函数见表
函数 | 描述 |
mkdir(path[,mode=0o777]) | 创建path指定的一个目录 |
makedirs(name[,mode=0o777]) | 创建多级目录,name表示为“path1\path2\…” |
rmdir(path) | 删除path指定的目录 |
removedirs(path) | 删除path指定的多级目录 |
listdir(path) | 返回path指定目录下的所有文件名,返回值为列表 |
getcwd() | 返回当前工作目录 |
chdir(path) | 改变当前目录为path指定的目录 |
walk(op,topdown=True,οnerrοr=None) | 遍历目录树 |
path.isfile(path) | 当path指定的是一个文件的名称时,返回True,否则返回False |
path.isdir(path) | 当path指定的是一个文件夹的名称时,返回True,否则返回False |
stat(fname) | 返回有关fname的信息,如大小(单位为字节)和最后一次修改时间。详细功能参见在线文档 |
2、目录的遍历
os.walk()返回的是一个三元组:tupple(dirpath, dirnames, filenames), 其中第一个为起始路径,第二个为起始路径下的文件夹,第三个是起始路径下的文件。 dirpath是一个string,代表目录的路径; dirnames是一个list,包含了dirpath下所有子目录的名字; filenames是一个list,包含了非目录文件的名字。这些名字不包含路径信息,如果需要得到全路径,需要使用 os.path.join(dirpath, name)。
3、其他目录相关操作
返回当前目录中的文件和文件夹; 返回当前目录中的指定类型文件; 返回当前目录中所有文件的大小总和等。
以下为以上内容的部分示例
def make_story():
f=open('story.txt','w')
f.write('Marry had a little lamb,\n')
f.write('and then she had some more.\n')
f.close()
make_story()
#在文件尾添加内容
def add_to_story(line,fname='story.txt'):
f=open(fname,'a')
f.write(line)
f.close()
add_to_story('haha!\n')
# 使用readline()读文件
f=open('story.txt')
while True:
line=f.readline()
if line:
print(line[:-1]) #去掉每行的换行符
else:
break
f.close()
print()
#多行读取方式,使用readlines()
f=open('story.txt')
lines=f.readlines()
for line in lines:
print(line[:-1])
f.close()
print()
#使用read()读文件
f=open('story.txt')
context=f.read()
print(context)
f.close()
print()
#使用read()返回指定字节的内容
f=open('story.txt')
context=f.read(5) #读取文件前五个字节内容
print(context)
print(f.tell())#返回文件对象当前指针位置
context=f.read(5)#继续读取5个字节内容
print(context)
print(f.tell())#输出文件当前指针位置
f.close()
#使用writelines()写文件
f=open('hello.txt','w+')
context=['hello world!\n','hello China!\n']
f.writelines(context)
f.close()
#将字符串插入到文件开头
def insert_tilte(title,fname='story.txt'):
f=open(fname,'r+')
temp=f.read()
temp=title+'\n'+temp
f.seek(0)
f.write(temp)
f.close()
insert_tilte('long long ago,')
f=open('companies.txt','w')
f.write('GOOGLE Inc.\n')
f.write('Microsoft Corporation\n')
f.write('Apple Inc.\n')
f.write('Facebook,Inc\n')
f.close()
f1=open('companies.txt','r')
cNames=f1.readlines()
for i in range(0,len(cNames)):
cNames[i]=str(i+1)+' '+cNames[i]
f1.close()
f2=open(r'scompanies.txt','w')
f2.writelines(cNames)
f2.close()
#文件的删除
import os
open('hello.txt','w')
if os.path.exists('hello.txt'):
os.remove('hello.txt')
#用read()、write() 实现文件 复制
#创建文件hello.txt
src=open('hello.txt','w')
context=['hello world\n','hello China\n']
src.writelines(context)
src.close()
#将hello.txt 复制到hello2.txt
src=open('hello.txt','r')
dst=open('hello2.txt','w')
dst.write(src.read())
src.close()
dst.close()
#使用shutil模块实现文件的复制和移动
import shutil
#将hello.txt 的内容复制给hello2.txt
shutil.copyfile('hello.txt','hello2.txt')
#修改文件名
import os
ls=os.listdir('.')#返回当前目录的文件列表
if 'hello.txt1' in ls:
os.rename('hello1.txt','hello.txt')
# 7 从hello.txt 文件中统计字符串‘hello’出现的次数
print()
import re
f1=open('hello2.txt','r')
count=0
for s in f1.readlines():
ls=re.findall('hello',s)
if len(ls)>0:
count+=ls.count('hello')
print('查找到'+str(count)+'个hello')
f1.close()
#将hello.txt 中字符串'hello'全部替换为'hi',并将结果存为hello2.txt中
f1=open('hello.txt','r')
f2=open('hello2.txt','w')
for s in f1.readlines():
f2.write(s.replace('hello','hi'))
f1.close()
f2.close()
#二进制文件存取
print()
import pickle
def make_picked_file():
grades={'tom':[84,88,90,90],
'jack':[77,87,97,88],
'marry':[85,None,90,90],
'alan':[100,88,90,95]
}
outfile=open('grades.dat','wb')
pickle.dump(grades,outfile)
def get_pickle_data():
infile=open('grades.dat','rb')
grades=pickle.load(infile)
return grades
make_picked_file()
print(get_pickle_data())
#目录的创建和删除
import os
os.mkdir('hello6') #创建path指定的一个目录
os.rmdir ('hello6')#删除path 指定目录
os.makedirs('1hello\world')
os.removedirs('1hello\world')
#用递归函数遍历目录
import os
def VisitDir(path):
ls=os.listdir(path) #返回path 指定目录下的所有文件名和目录名
for p in ls:
pathname=os.path.join(path,p) #连接两个或多个路径
if not os.path.isfile(pathname):
VisitDir(pathname)
else:
print(pathname)
if __name__=="__main__":
path=r'C:\Users\Administrator\Desktop'
VisitDir(path)
#使用os.walk
import os
def VisitDir(path):
for root,dirs,files in os.walk(path):
for filepath in files:
print(os.path.join(root,filepath))
if __name__=="__main__":
path=r'C:\Users\Administrator\Desktop'
VisitDir(path)
#返回当前目录中的所有文件的大小总和
import os
def list_cwd():
return os.listdir(os.getcwd()) #返回当前目录中的所有文件名和子目录名
def size_in_bytes(fname):
return os.stat(fname).st_size
def cwd_size_in_bytes():
total=0
for name in list_cwd():
total+=size_in_bytes(name)
return total
print(cwd_size_in_bytes())