当程序执行完毕之后,所有存储再在内存中的数据都会消失,这时,如果需要将执行结果存储的磁盘上,就必须通过文件模式来加以保存。

文件时计算机中数字、数据和信息的集合,是一种存储数据的单位,这些数据以字节的方式存储,可以是一份报告、一张图片或一个可执行程序,因而包括数据文件、程序文件或可执行文件等格式。使用文件存取数据是数据加工、处理和存储中非常重要的一环。

1.认识文件

在程序的运行过程中,所有数据都存储在内存中。一旦程序结束,之前输入的数据会全部消失。在程序执行过程中,如果要将加工、处理或计算的数据永久保存下来,就必须将数据写入文件并存放在非挥发性的存储介质中,例如硬盘。每个文件都必须有文件名,文件名分为主文件名和扩展名,中间以句点分隔,扩展名的功能在于记录文件的类型。

1.1 文件的种类

文件如果按存储方式来分类,可以分为文本文件与二进制文件两种

文本文件

文本文件是以字符编码的方式进行存储的,在Windows操作系统的记事本程序中,默认是以ASCII编码来存储文本文件的,每个字符占1字节。例如,在文本文件中存入一个10位的整数1234567890,由于是以字符串按顺序存入的,因此总共需要10个字节来存储这个整数。

二进制文件

所谓二进制文件,就是以二进制格式进行存储的文件,也就是将内存中的数据原封不动地保存到文件中,这种存储方式适用于非字符为主的数据,如果记事本打开这类文件,只会看到一堆乱码

其实,除了以字符为主的文本文件外、所有的数据都可以说是二进制文件,例如编译过后的程序文件、图像或视频文件等。二进制文件的最大有点在于访问速度快、占用控件小以及可随机存取,在数据应用上比文本文件更加合适。

1.2 认识文件目录

在计算机或移动设备中,一个目录或文件夹中存储着一组文件和其他一些目录(文件夹)。一个文件系统可能包含成千上万个文件和目录,并以一种有组织的方式进行管理,以达到有效存储文件的目的。在一个目录中的另一个目录被称作它的子目录(子文件夹)。这些目录构成了层级或树形结构。

文件系统是一种存储和组织计算机数据的方法,通过文件系统的管理工具可以帮助用户在存取文件时变得更为直觉和方便。事实上,在文件系统中,使用文件和目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,这样用户存储数据时不必关心数据存储在硬盘的实际地址及占用多少地址空间,只需记住这个文件所属目录和文件名即可。

不同的操作系统所采用的文件系统会有所不同,例如早期MS-DOS采用的文件系统为FAT(File Allocation Table,文件分配表),而现今较常见的操作系统Windows7/8/10的文件系统则有FAT32、NTFS(New Technology File System 新技术文件系统)或exFAT(Extended File Allocation Table 扩展文件分配表)。

1.3 绝对路径与相对路径

首先说明绝对路径和相对路径的差异。简单地说,绝对路径指的是一个绝对的位置,并不会随着当前目录的改变而改变,例如

C:\Windows\system\

相对路径是相对于当前目录的路径表示法,因此相对路径所指向的文件或目录会随着当前目录的不同而改变。通常我们用”.”代表当前目录,而用”..”代表上一级目录。

2.文件的读写

2.1 文件的写入

Python在处理文件的读取与写入时都是通过文件对象,因此,无论时进行文件的写入或读取操作。第一项工作就是调用Python的内部函数open()来创建文件对象。所谓文件对象(File Object)就是一个提供存取文件的接口,它并非实际的文件。当打开文件之后,必须通过文件对象指定读(Read)或写(Write)的操作。

open()函数的语法如下:

open(file,mode)
  • file:以字符串来指定想要打开文件的路径和文件名。
  • mode:以字符串指定打开文件的存取模式。

关于文件的存取模式,参见下表

mode 说明
r 读取模式(默认值)
w 写入模式,创建新文件或覆盖旧文件
a 附加(写入)模式,创建新文件或附加到旧文件的末尾
x 写入模式,文件不存在时就创建新文件,文件存在则报错
t 文本模式(默认)
b 二进制模式
r+ 更新模式,可读可写,文件必须存在,从文件开头进行读写
w+ 更新模式,可读可写,创建新文件或覆盖旧文件的内容,从文件开头进行读写
a+ 更新模式,可读可写,创建新文件或从旧文件末尾进行读写

如果调用open()创建文件的对象操作成功了,就会返回文件对象;如果创建文件失败了,就会发生错误。当以读取模式r打开文件时,如果该文件不存在,就会发生错误。

例如,下面的程序语句是以读取模式打开一个名称为C:\test.txt的文件,如果通过这个路径找不到这个文件,就会发生FileNotFoundError的错误信息

file1 = open('C:\\test.txt','r')

# 返回
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\test.txt'

如果以写入模式打开文件,当文件不存在时,系统会自动创建该文件,而不会报错

file1 = open('C:\\test.txt','w')

需要注意的是,调用open()函数打开文件时,所指定的文件路径必须以转义符”\”来表示”\”,如:

file = open('C:\\lab\\test.txt','w')

还可以在绝对路径前面加r来告知编译系统,r后随的路径字符串时原始字符串,如:

file=open(r'C:\lab\test.txt','w')

也就是说,对于文本而言,要将数据写入文件中,必须先调用open()函数创建新文件,再使用文件对象所提供的write()方法将文字写入文件,最后调用close()方法关闭文件。

注意写入文件时会从文件指针当前所在的位置开始,因此写入文件时,必须指定存取模式。文件指针用来记录文件当前写入或读取到了哪一个位置。

content = """
越女采莲秋水畔,窄袖轻罗,暗露双金钏。

照影摘花花似面,芳心只共丝争乱。

鸡尺溪头风浪晚,雾重烟轻,不见来时伴。

隐隐歌声归掉远,离愁引看江南岸。
"""
# 创建新文件
fn = open('.\\神雕侠侣.txt', 'wt')
# 将字符串写入文件
fn.write(content)
# 关闭文件
fn.close()

2.2 文件的读取

文件读取同样需要先调用open()方法打开指定的文件,接着使用文件对象所提供的read()、readline()或readlilnes()方法从文件读取数据,最后调用close()方法关闭文件

前面提到,读取文件和写入文件有不同之处,如果以读取模式打开文件,当文件不存在会发生找不到文件的错误。为了避免类似错误的发生,可以再打开文件之前用os.path模块所提供的isfile(file)函数来检查指定文件名的文件是否存在,如果文件存在返回True,否则返回False.

import os.path
# 调用isfile()方法检查文件是否存在
if os.path.isfile('test.txt'):
    fb = open('test.txt', 'r')
    for word in fb:
        print(word)
else:
    print('文件不存在')

# 返回 
文件不存在

下面来认识读取文件的三种方法

1.read()方法

调用read()方法读取数据会从文件当前指针所在的位置一个一个的字符取读取,读取万指定个数的字符之后就返回该字符串,其语法如下:

read(n)

如果将参数n省略,就会以字符串类型返回文件的所有数据。特别注意,调用此方法时如果没有指定读取的字符数,当文件很大时,会消耗大量系统资源。

下面的实例,通过read()方法读取所有字符串

# 调用open()方法打开指定的文本文件
fn = open('.\\神雕侠侣.txt', 'r')
# 调用read()方法读取文件的内容
text = fn.read()
print(text)
fn.close()

返回结果为

越女采莲秋水畔,窄袖轻罗,暗露双金钏。

照影摘花花似面,芳心只共丝争乱。

鸡尺溪头风浪晚,雾重烟轻,不见来时伴。

隐隐歌声归掉远,离愁引看江南岸。

也可以在read()方法中传入一个参数来告知要读取几个字符

# 调用open()方法打开指定的文本文件
fn = open('.\\神雕侠侣.txt', 'r')
# 调用read(n)方法读取文件的内容
text = fn.read(20)
print(text)
text = fn.read(40)
print(text)
fn.close()

返回结果为

越女采莲秋水畔,窄袖轻罗,暗露双金钏。


照影摘花花似面,芳心只共丝争乱。

鸡尺溪头风浪晚,雾重烟轻,不见来时伴。

我们知道文件指针指向文件当前要写入或读取的位置,前面两个范例中的文件指针的移动是由系统自行移动的。如果要移到指定的位置,就需要调用seek(offset)方法,此方法将文件指针移动到offset+1个字节,例如seek(0)表示将文件指针移到文件第一个字节的位置。

#调用open()方法打开指定的文本文件
fn = open('.\\神雕侠侣.txt', 'r')
# 将文件指针移到文件起始处
fn.seek(0)
# 调用read()方法读取文件内容
text = fn.read(7)
print(text)

返回结果为

越女采莲秋水畔

综合上述介绍的方法,接下来将示范如何进行文件赋值

import os.path
import sys

# 判断文件是否存在
file_path = '.\\CondorHeroes.txt'
original_path ='.\\神雕侠侣.txt'


if os.path.isfile(file_path):
    print('指定文件已存在,不要进行复制')
    sys.exit()
else:
    # 打开原始文件
    ori_file = open(original_path,'r')
    copy_file = open(file_path,'w')
    text = ori_file.read()
    text = copy_file.write(text)
    print('文件复制完成')
    ori_file.close()
    copy_file.close()

2.readline()方法

read()方法时一次读取一个字符,但是readline()方法可以整行读取,并将整行的数据内容以字符串的方式返回,如果所返回的字符串是空字符,就表示已读到文件末尾。以下实例就是调用readline()方法一次一次读取的方式将文件内容读取再输出

obj = open('chapter.txt','r')
line = obj.readline()
while True:
    print(line)
    line = obj.readline()
obj.close()

上面的实例也可以用for循环来改写:

obj = open('chapter.txt','r')
for line in obj:
    print(line)
obj.close()

3.readlines()方法

readlines()方法会一次读取文件的所有行,再以列表类型返回所有行。

with open('introduct.txt','rt') as foin:
    total = foin.readlines() # 一次读取所有行
print('行数',len(total))
for line in total:
    print(line,end='')

3.二进制文件

计算机上的数据并非只有文本类型,常见的数据格式还有图像、音乐或者经过编译的程序等,这些数据无法以文本类型的方式来处理,而必须以其他数据格式来处理。如果要创建二进制文件,就在open()方法的参数中加入“b”,即表示二进制,否则会引发错误,而内部函数bytearray()用于读取二进制数据。

tmp = bytearray(range(8))
# 二进制数据写入
with open('bytedata','wb') as fob:
    fob.write(tmp)
# 二进制数据读取
with open('bytedata','rb') as fob:
    fob.read(3)
    print(type(tmp))
    print('二进制:',tmp)

发表评论

电子邮件地址不会被公开。 必填项已用*标注