文章目录
1.什么是文档
数据由于表现形式的不同,会被分为各种文件:
我们知道冯·诺依曼架构包括:输入输出设备、存储器、运算单元和处理器。 内存的存储系统分为内存和硬盘:
内存和硬盘的比较:
内存空间较小,硬盘空间较大 内存访问较快,硬盘访问较慢 内存成本较高,硬盘成本较低 内存数据容易丢失,硬盘数据可持久存储
我们电脑中C盘、D盘的内容都是硬盘上的内容,也都是文件:
2. 文件路径
文件夹也称为目录,也属于文件。 我们将层层目录组成的字符串称为“文件的路径”。 例如我电脑中QQ可执行程序的路径为:C:\Files (x86)\\QQ\Bin
文件路径可以看作是硬盘上文件的标识,每个文件对应的路径是唯一的。 知道文件路径,就可以知道该文件在硬盘上的详细位置; 您可以进一步了解文件中的内容。
补充说明
目录名之间,使用反斜杠\来分隔,其实使用斜杠/也可以。 前者使用较多,在其他系统中更多使用斜杠来分隔,因为反斜杠在字符串中具有特殊的含义,可以表达含义。
3.打开文件
创建一个文档文件test.txt用于测试:
要使用 open 函数打开文件:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r')
print(f)
print(type(f))
-------运行结果-------
# 包含文件的路径、打开方式、编码方式这三个信息
<_io.TextIOWrapper name='C:/Users/86158/Downloads/Python/test.txt' mode='r' encoding='cp936'>
# Python内部给文件对象起的名字
<class '_io.TextIOWrapper'>
开放函数分析
补充说明
1)打开的文件必须存在于给定路径中,否则会抛出异常
2)文件对象是一个句柄
open的返回值是一个文件对象,怎么理解?
文件对象就像遥控器,文件就像电视。 我们想要操作电视(开关、调节频道、调节音量),我们可以直接按电视上的按钮,但这太麻烦了,我们通常躺在沙发上通过遥控器来操作; 对于模拟文件,我们可以直接去硬盘上读写文件,为了方便我们也使用文件对象来完成这些操作。
在计算机中,这种用于远程控制的“遥控器”也被称为“手柄”。
4. 关闭文件
使用 close 方法关闭已经打开的文件:
f.close()
打开并使用文件后请务必关闭该文件!
打开文件实际上就是申请某种系统资源。 当文件不再使用时,应及时释放资源; 否则,文件资源可能会泄漏,并进一步导致代码其他部分无法打开文件。
正是因为系统的资源是有限的,所以程序可以打开的文件数量是有上限的。 通过以下代码测试
# 1、创建一个列表,用来存储文件对象
fList = []
# 2、无限地打开文件
count = 0
while True:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r')
fList.append(f)
count = count + 1
print(f'打开的无间隔数:{count}')
-------运行结果-------
...
打开的无间隔数:8187
打开的无间隔数:8188
打开的无间隔数:8189
OSError: [Errno 24] Too many open files: 'C:/Users/86158/Downloads/Python/test.txt'
发现允许打开的文件数上限为:8189
我们可以通过一些设置项来配置最大可以打开的文件数。 但无论配置多少,它们都不是无穷无尽的,我们还是需要及时关闭它们,释放资源。
另外,还有一个重要的机制:垃圾收集机制(GC),它会自动释放未使用的变量。
这次我们仍然无限地打开文件,但不再将文件对象保存到列表中:
count = 0
while True:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r')
count = count + 1
print(f'打开的无间隔数:{count}')
这次运行后发现不会抛出异常。 之前抛出异常是因为我们把所有打开的文件对象都存到了列表中,然后操作系统判断我们后面可能会用到这些文件对象,所以就没有回收它们; 这次我们只是简单地打开文件,没有对它们进行任何操作。 循环结束后,操作系统会自动回收之前打开的文件对象。
总结:虽然给了我们后手,但还是让我们在一定程度上避免了内存泄漏。 但你不能完全依赖自动回收机制,因为它无法绝对及时地释放,所以你应该尝试手动释放它以确保万无一失。
补充:为什么要设置打开文件数上限为8189?
因为:8189 + 3 = 8192 => 2^13
计算机中所有的数据都是用二进制数来表示的,所以计算机中很多数字都是用2的n次方的形式来表示的; 也就是说,在程序员眼中,1000并不是一个很整齐的数字,1024 => 2^10 这是一个比较整齐的数字。
回到正题,8189中丢失的三个文件是什么? 事实上,每个程序启动时都会默认打开三个文件:
缺少的三个文件就是它们,而且这三个文件在程序启动之初就已经被打开了。
5. 写入文件 1. 清除写入
使用write方法写入文件内容:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'w')
f.write('hello')
f.close()
编译运行后,观察test.txt文件,成功写入字符串“hello”:
注意,如果要写入文件,则在打开文件时需要使用'w'方法。 如果在 'r' 方法中打开它,将会抛出异常:
2.追加写入
以写模式打开文件实际上有两种情况,以直写模式打开和以追加写模式打开:
# 用追加的方式对 test.txt 文件进行写入
f = open('C:/Users/86158/Downloads/Python/test.txt', 'a')
f.write('112233')
f.close()
观察test.txt文件的内容,发现新写入的内容被追加到了原来内容的末尾:
这次用“w”打开文件并写入:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'w')
f.write('world')
f.close()
发现源文件内容被清空,然后写入新内容:
最后还要注意一点:如果文件对象已经被关闭,则意味着系统中与该文件相关的内存资源已经被释放。 这时候如果强行写入,也会抛出异常:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'w')
f.close()
# error:对已经关闭的文件进行写操作
f.write('hello')
抛出异常:
六、读取文件 1.使用read方法读取
假设test.txt文件内容如下:
接下来,我们以‘r’模式打开文件,然后使用read函数读取文件内容; read函数的参数是要读取的字符数,返回值是一个字符串:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r')
ret = f.read(2)
print(ret)
f.close()
编译后抛出异常:
原因是文件内容对于中文的编码方式是utf8; 当我们打开文件时,文件操作的编码方式默认为gbk,两者不匹配,因此文件内容的读取失败:
我们这里采用的方法是让代码按照utf8的方式进行处理。 与gbk相比,utf8是一种应用更为广泛的编码方式。
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r', encoding='utf8')
ret = f.read(2)
print(ret)
f.close()
-------运行结果-------
床前
2.使用for循环逐行读取
使用for循环直接遍历文件对象,就可以一行一行的读取内容:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r', encoding='utf8')
for line in f:
print(line)
f.close()
-------运行结果-------
床前看月光
疑是地上霜
举头望山月
低头思故乡
观察结果,发现每句话结束后,下面都会多出一行。 为什么是这样?
之所以多了一个空行,是因为原来读取的内容每行末尾都有一个'\n',如果这里用print打印的话,会自动添加换行符。
我们可以为 print 多设置一个参数来修改 print 自动添加换行符的行为
重写代码并观察结果:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r', encoding='utf8')
for line in f:
print(line, end='')
f.close()
-------运行结果-------
床前看月光
疑是地上霜
举头望山月
低头思故乡
3.使用方法读取整个文件的内容
该方法可以一次性读取整个文件的内容,无需传递参数,它会逐行读取文件内容,然后将结果整理成列表作为返回值,返回给外界:
f = open('C:/Users/86158/Downloads/Python/test.txt', 'r', encoding='utf8')
ret = f.readlines()
print(ret)
f.close()
-------运行结果-------
['床前看月光 \n', '疑是地上霜\n', '举头望山月 \n', '低头思故乡']
PS:如果文件很大,内容很多,不建议使用该方法。 此时读取文件内容的效率不高。
七。 上下文管理器 1. 什么是上下文管理器?
通过上下文管理器打开和操作文件,我们不必担心文件最终是否被忘记关闭,从而导致资源泄漏。
不同的高级语言有不同的防止资源泄漏的管理方法:
2. 为什么要有上下文管理器?
有些情况防不胜防,因为一些代码逻辑原因,我们无法保证文件最终被关闭:
3. 如何使用上下文管理器?
打开文件后,很容易忘记关闭它。 提供了上下文管理器来帮助程序员自动关闭文件。
语法如下:
with open('d:/test.txt', 'r', encoding='utf8') as f:
# 这里进行文件的处理逻辑,比如
lines = f.readlines()
print(lines)
它有以下两个功能:
例子: