文件永久存储

第七章文件:永久存储

1.文件的打开和关闭
在Python中可以使用内置函数open()打开文件,语法如下:
f = open(name, mode)(name和mode都得加引号)
open()主要有两个参数:name 和 mode。name是文件的路径或名称,如果只有文件名,没有路径,Python解释器会在当前脚本的目录中去搜索该文件并打开;mode是文件的打开模式标记,表示文件的使用方式,mode参数可以省略,省略时表示文件以只读的模式打开。
在这里插入图片描述
操作文件对象的方法
open()操作正常完成后,会返回一个文件对象,这个对象包含了文件的属性和可以对文件执行操作的方法。通过这个文件对象,可以读取或修改文件。
fileObject.close():关闭文件;
fileObject.flush():刷新文件内部缓冲,把内部缓冲区的数据立刻写入文件;
fileObject.next():返回文件的下一行;
fileObject.read([size]):从文件读取size个字符;
fileObject.readline():从文件中读取整行;
fileObject.readlines():读取文件中的所有行并返回列表;
fileObject.write(str):向文件写入字符串;
fileObject.writelines(seq):向文件写入字符串列表。
文件的关闭
在对文件进行写入操作时,系统并不会立刻把所有数据写入到磁盘。数据先在内存中缓存,等到空闲的时候再写入到磁盘。当调用fileObject.close()方法关闭文件时,会确保系统把剩余没有写入的数据全部写入到磁盘。所以为了保证数据安全,在打开文件进行读写操作后,要记得关闭文件。一旦关闭了文件,该文件对象依然存在,但是无法再通过它来操作文件内容了。
最好用方便的还是with-as来打开和关闭文件

通常使用函数open()打开文件之后,必须使用close()方法妥善地关闭文件,以避免数据丢失或受损。这种操作略显繁琐,优选的最佳实践方式是使用“with-as”语句,语法如下:
with open(name, mode) as f:
使用with-as语句获取文件对象f,是一种被Python称为“上下文管理器”的方式:f是指向文件的对象,在使用with-as打开文件的代码块内,文件是打开的,可以进行读写操作。然而,一旦代码从with-as的代码块中退出,文件会自动关闭。也就是说,使用with-as的上下文管理器,我们只管打开文件,并在需要的时候对文件进行操作,而Python则会在合适的时候自动将其关闭。
2.文件的读写操作
一旦使用open()获取了文件对象,就可以调用它的方法来读取文件的内容或者向文件写入新数据。对于文本文件,读取操作会返回字符串类型的数据,写入操作也需要传入字符串类型的数据。
在这里插入图片描述
一、fileObject.read([size]):调用read()方法,会一次性读取全部文件内容

with open("my_file.txt", "r") as f:
    var_1 = f.read()
        print(var_1)
        var_2 = f.read()    
        print(var_2)  # 文件指针已经移到末尾,所以输出显示为空

在首次读取了文件全部内容以后,再次进行读取时,发现输出显示为空,不能重复读取文件内容。如果想重复读取,应该如何解决?其实这和文件指针有关,在对文件进行操作时,其内部会有一个指针来定位当前位置,这就是文件指针。文件指针可以理解为:是从文件开始位置的偏移量,相当于文件内容的标记,是下一个操作开始的地方,而不是当前操作结束的地方。当使用文件对象读写数据时,文件指针会自动向后移动:读写了多少个数据,文件指针就自动向后移动多少个位置。“r”模式打开文件时,文件指针在文件开始的位置,在读取文件的全部内容后,文件指针就移动到了文件末尾,如图所示。再次进行读取时,就不能获取任何信息了,所以f.read()方法返回一个空字符串。
和文件指针有关的方法有两个:fileObject.tell()、fileObject.seek()。
fileObject.tell()方法可以返回文件指针的当前位置,例如:

with open("my_file.txt", "r") as f:
    print(f.tell())  # 0    (文件的开始位置)
    var_1 = f.read()
    print(f.tell())  # 46   (文件的结束位置

在打开文件,文件指针在起始位置,f.tell()方法返回值为0。在读取文件的全部内容以后,文件指针移到了末尾位置,f.tell()方法返回值为46(在Windows系统中换行符按照约定被替换为 \r\n,即:一个换行符占两个字节,所以14×3 + 2×2 = 46)
fileObject.seek()方法可以移动文件指针,有两个参数:fileObject.seek(offset,whence)
offset:指针移动offset个字符,正数往文件末尾方向移动,负数往文件开始方向移动。
whence:可选参数,表示要从哪个位置开始移动文件指针;0(默认值)表示从文件开始位置移动,1代表从当前位置移动,2代表从文件结束位置移动。
如果想把文件指针移动到文件的开始位置,可以使用:f.seek(0,0)
如果想把文件指针移动到文件的第2行第3个字符,可以使用:f.seek(18,0)。
使用read()方法读取文件很方便,可以一次性读取全部的文件内容。但是对于大文件,一次性读取全部内容,会占用大量的系统资源。这种情况,一般会限制单次读取文件的大小,每次最多读取size个字节的内容,反复调用read(size)方法。例如:
var_1 = f.read( 1024 )
二、fileObject.readline([size])
readline()用于从文件中读取一行数据,当遇到换行符时一次读取结束。参数size表示读取多少个字符,-1是默认值,表示读取整行数据,如果size大于一行的实际字符数,读取会在遇到换行符时结束。也就是说fileObject.readline([size])方法是在size和换行符这两个条件中任意一个满足时结束读取。readline()方法返回一个由读取内容组成的字符串。
三、fileObject.readlines([sizehint])
readlines()方法用于读取文件所有行,返回值是一个列表,由每行文本构成的字符串作为其中元素。参数sizehint表示读取字符的个数,如果sizehint大于前n行的总字数但小于前n+1行的总字数,readlines()方法会读取文件的前n+1行文本。也就是说,readlines()方法返回的一定是完整的行数据,大多数情况下,返回数据的字节数会略比sizehint指定的值大一些(除最后一次调用 readlines(sizehint) 方法的情况除外)。
文件的写入操作
在这里插入图片描述
3.文件的其他操作
读取文件内容更为便捷的方法是直接对文件对象进行迭代,和字符串、列表、元组一样,可以遍历文件对象的所有值,你可以在for循环、列表推导式中自动逐行读取文件,例如:

with open('my_file.txt', 'r') as f:
    for line in f:
    print(line.rstrip())  

绝对路径和相对路径
如果打开的文件和脚本文件不在同一目录,就需要指明路径。例如,打开D盘根目录下的 test_file.txt 文件:
with open(‘D:\test_file.txt’, ‘r’) as f: # \t被解析为水平制表符
解决方法:
with open(‘D:/test_file.txt’, ‘r’) as f:

with open(r‘D:\test_file.txt’, ‘r’) as f: # 推荐
在表示路径时,除了能够使用从根目录(C:\、D:\等)开始的绝对路径外,还可以使用相对于当前工作目录(cwd,current working directory)的相对路径。当前工作目录一般而言可以认为是脚本文件所在的目录。在Python 3 中,使用如表所示的方式表示相对路径:
在这里插入图片描述
我们已经学习了如何把字符串存储在文件中,如果把整型、列表、元组等对象存储在文件中,要先把它们先转换成字符串,再进行写入。使用时,还需要把它们变成原来的类型。把对象转换成字符串,可以使用函数str()。把文本文件的字符串转换成原先的对象,需要区分不同的情况分别处理:如果是整数、浮点数等,可以使用函数int()、float();如果是列表、字典等,可以使用内置函数eval()。eval()用来执行一个字符串表达式,并返回表达式的计算结果,使用函数eval()可以将字符串转换为列表、元组、字典。
var1 = [0, 1, 2, 3]
var2 = {‘a’: 1, ‘b’: 2, ‘c’: 3}
with open(r’.\subPack2\file_1.txt’, ‘w’) as f:
f.write(str(var1) + ‘\n’) # 列表var1转换为字符串写入文件
f.write(str(var2)) # 字典var2转换为字符串写入文件
with open(r’.\subPack2\file_1.txt’, ‘r’) as f:
var = []
for line in f:
var.append(eval(line)) # 从文本文件中恢复列表和字典

运行结果:[[0, 1, 2, 3], {‘a’: 1, ‘b’: 2, ‘c’: 3}]

print(var)
4.CSV文件的读写操作
CSV(Comma Separated Values,逗号分隔值)是一种通用的、相对简单的文件格式,在工程、科学、商业等领域被广泛采用,常用来在不同程序之间交换表格数据,使用CSV格式可以存储一维和二维数据。
程序是一组计算机能识别和执行的指令序列,这些指令通常是用来处理数据的,数据经过处理才具有价值,经过整理、转换、分析、综合的数据才能称为是信息。除了单一的数据类型(整数、浮点数等),相互之间存在一种或多种特定关系的数据则需要合理有序地组织起来,以提高数据存储的效率和处理的速度。
根据数据的关系不同,数据组织可以分为一维数据、二维数据和高维数据:一维数据由对等关系的有序或无序数据构成,采用线性方式组织,对应于数学中的数组和集合等概念;二维数据由关联关系的数据构成,采用表格方式组织,对应于数学中的矩阵;高维数据由键值对类型的数据构成,采用对象方式组织,属于整合度更好的数据组织方式。
一维数据具有线性特点,例如我国四个中央直辖市具有对等关系,可以表示为一维数据:[“北京市”, “上海市”, “天津市”, “重庆市”]。
二维数据,也称表格数据,常见的表格都属于二维数据。例如,2020年国内生产总值排名前五的省市自治区是二维数据,如表所示。其中表头(表格第一行)可以看成是二维数据的一个维度,也可以看做是数据额外的说明。
在这里插入图片描述
高维数据在网络系统中十分常用,HTML、XML、JSON等都是高维数据组织的语法结构。以描述“历届党代会”的JSON格式为例,下面给出了这种高维数据的表示形式,其中:“历届党代会”和后续内容通过冒号(:)形成一个键值对,每个内容中“党代会”、“时间”、“地点”、“中心议题”分别与后面的内容形成键值对,内容按照层级采用逗号和大括号组织起来。高维数据相比于一维和二维数据,能表达更加灵活和复杂的数据关系。
一维数据是最基础的数据组织形式,多个一维数据组合在一起,可以构成二维数据,一维、二维数据可以存储为CSV文件。CSV文件是在电子表格和数据库中普遍使用的导入和导出数据格式,以纯文本形式存储表格数据(数字和文本),包含可打印的ASCII或Unicode字符。它使用特定的结构来存储表格数据,文件中的每一行都是一个数据记录,每个记录由一个或多个字段组成,用逗号或者其他字符(如制表符、冒号、分号)分隔,可以有任意数量的记录,仅受文件大小的限制。所有的记录都有完全相同的字段序列,相当于一个结构化表格的纯文本文件。
CSV文件(使用逗号作为分隔符)的结构如下所示:
column 1 name, column 2 name, column 3 name
first row data 1, first row data 2, first row data 3
second row data 1, second row data 2, second row data 3
通常,CSV文件第一行用于标识数据列的名称,之后的每个后续行才是实际的数据。例如,之前的二维数据使用CSV存储后内容为:
省市自治区,排名,按现价计算(亿元)
广东,1,110761
江苏,2,102719
山东,3,73129
浙江,4,64613
河南,5,54997
CSV文件是操作表格和数据库最常用的输入输出格式,虽然文件的格式大致相似的,但因为缺少合适的描述规范,所以不同应用的输入输出格式会有细微的差别。Python自带的csv库提供了读写CSV文件的一些对象,可以高效处理CSV文件中的数据,同时还可以隐藏读写的细节,使你不必纠结于这些麻烦的小细节。
使用车速库操作csv文件
CSV文件是操作表格和数据库最常用的输入输出格式,虽然文件的格式大致相似的,但因为缺少合适的描述规范,所以不同应用的输入输出格式会有细微的差别。Python自带的csv库提供了读写CSV文件的一些对象,可以高效处理CSV文件中的数据,同时还可以隐藏读写的细节,使你不必纠结于这些麻烦的小细节。
一、读取CSV文件
1、读取CSV文件
csv.reader(csvfile)是读取CSV文件最常用的方法,参数csvfile是一个文件类型的对象,csv.reader()返回一个可以按行读取的对象。具体地说:首先使用内置函数open()将CSV文件作为文本文件打开,然后将其传递给csv.reader( csvfile )的参数csvfile,csv.reader()会返回一个可以按行读取的reader对象,包含了CSV文件的内容,最后遍历reader对象完成读取工作。
2、将 CSV 文件读取为字典
csv.DictReader()可以将CSV文件读取为字典。
二、写入CSV文件
1、写入 CSV 文件
csv.writer()可以返回一个writer对象,调用writer对象的write_row()方法就可以写入一行数据。
2、将 CSV 文件读取为字典
csv.DictReader()可以将CSV文件读取为字典。
在把字典写入的时候,需要传入两个参数,一个是文件对象:csv_fp,另一个是数据列名称列表:fieldnames。fieldnames是必需的参数,没有数据段名称列表,就无法知道应该使用哪些key来从字典中检索value。调用writer.writeheader()方法,可以把数据段名称列表:fieldnames写为CSV文件的第一行(表头)。调用writer.writerow()方法,传入相应字典参数,就可以把字典写入为CSV文件的一行数据。
5.pickle:存储Python的原生对象
前面讨论了如何使用函数eval()把字符串转换成对象。函数eval()是一个功能过于强大的工具,可以直接运行Python的任何表达式,以至于会存在一些安全隐患,一些恶意用户甚至可以利用函数eval()执行删除文件、修改权限等敏感操作。如果想存储Python原生对象,但又对函数eval()的强大功能有所忌惮,无法信赖读取操作的数据来源,那么Python的标准库 pickle 会是个理想的替代,它安装时已经包含,可以直接import使用。Pickle以文件的形式保存对象,它可以把对象层次结构转换成字节流(二进制文件或类似字节的对象)保存到磁盘、数据库或服务器,这个过程称为是序列化(pickling或serialization);反过来,也可以把字节流转换成对象层次结构,这个过程称为是反序列化(unpickling或deserailization)。
Python中几乎所有的数据类型,包括列表,字典,集合,类等都可以用pickle进行序列化和反序列化。pickle主要提供了四种方法实现其功能,如表所示。
在这里插入图片描述
pickle.dumps()、pickle.loads()不涉及对文件的操作,pickle.dumps()方法将对象序列化并返回一个字节对象,而pickle.loads()对字节对象反序列化并返回一般对象:
`

import pickle
var1 = [0, 1, 2, 3]
var5 = pickle.dumps(var1)
print(var5)  		# 输出显示序列化后的字节对象,可读性差

var6 = pickle.loads(var5)
print(var6)  		# 运行结果:[0, 1, 2, 3]

`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值