文件操作的初识
用 python 代码对文件进行各种操作.
基本构成:
文件路径: path
打开方式: 读, 写, 追加, 读写, 写读......
编码方式: utf-8 / gbk / gb2312......
- f = open('文件路径或者相对路',encoding='编码方式',mode='模式') # 格式构成
- cotent = f.read()
- print(content)
- f.close()
代码解释:
open:
内置函数, open 底层调用的是操作系统的接口.
f:
变量, 约定俗成的变量名有 (f1,fh,file_handler,f_h), 这个变量还有一个名字, 叫文件句柄. 对亠件进行的任何操作, 都得通过文件句柄加'.'的方式.
encoding:
可以不写, 如果不写, 默认的编码本就是系统默认的编码.
- Windows: gkb
- Linux: utf-8
- MacOS: utf-8
- mode:
就是定义你的操作方式: r 为读模式.
f.read():
你想操作文件, 比如读文件, 给文件写内容, 等等, 都必须通过文件句柄进行操作.
f.colse():
关闭文件.(必须关闭, 否则会常驻内存.)
文件操作的三个步骤:
打开文件.
对文件句柄进行相应的操作.
关闭文件.
- # 打开文件, 得到文件句柄并赋值给一个变量
- f = open('文件. txt', 'r', encoding='utf-8') # 默认打开模式就为 r
- # 通过句柄对文件进行操作
- date = f.read()
- # 关闭文件
- f.close()
报错的原因:
UnicodeDecodeError: 文件存储时与文件打开时编码本不一致.
路径分隔符产生的问题:
解决方法: 在路径前加个 r
r'C:\Users\Desktop \ 文件. txt'
文件操作的: 读
文件操作的读, 有四种模式 (r,rb,r+,r+b),r+ 和 r+b 不常用, rb 操作的是非文本的文件, 比如: 图片, 视频, 音频. 每种模式有五种方法 (read(),read(n),readline(),readlines(),for).
r 模式
以只读方式打开文件, 文件的指针将会放在文件的开头. 是文件操作最常用的模式, 也是默认模式, 如果一个文件不设置 mode, 那么默认使用 r 模式操作文件.
举例:
- f = open('文件. txt', mode='r', encoding='utf-8')
- msg = f.read()
- f.close()
- print(msg)
read() 一次性全部读取
read() 将文件中的内容全部读取出来; 弊端: 如果文件很大就会非常的占用内存, 容易导致内存崩溃.
- f = open('测试', mode='r', encoding='utf-8')
- msg = f.read()
- f.close()
- print(msg)
- # 输出结果:
这是一行测试
A: 这是第二行
B: 这是第三行
C: 这是第几行
D: 这是我也不知道第几行
就这么地吧.
read(n) 指定读取到什么位置
在 r 模式下, n 按照字符读取
- f = open('测试', mode='r', encoding='utf-8')
- msg = f.read(4)
- f.close()
- print(msg)
- # 输出结果:
这是一行
readline() 按行读取
readline() 每次只读取一行, 注意: readline() 读取出来的数据在后面都有一个 \ n, 解决这个问题只需要在我们读取出来的文件后边加一个 strip() 就 OK 了
- f = open('测试', mode='r', encoding='utf-8')
- msg1 = f.readline()
- msg2 = f.readline().strip()
- msg3 = f.readline()
- msg4 = f.readline()
- f.close()
- print(msg1)
- print(msg2)
- print(msg3)
- print(msg4)
- # 输出结果:
这是一行测试
A: 这是第二行
B: 这是第三行
C: 这是第几行
readlines() 返回一个列表
readlines() 返回一个列表, 列表里面每个元素是原文件的每一行, 如果文件很大, 占内存, 容易崩盘.
- f = open('测试', mode='r', encoding='utf-8')
- print(f.readlines()) # 还可以这么写的, 哈哈
- f.close()
- # 输出结果:
- ['这是一行测试 \ n', 'A: 这是第二行 \ n', 'B: 这是第三行 \ n', 'C: 这是第几行 \ n', 'D: 这是我也不知道第几行 \ n', '就这么地吧.']
上面这四种都不太好, 如果文件超大, 内容超多, 他们就很容易将内存撑爆, 所以, 我们还有第五种方法.
for 循环
可以通过 for 循环去读取, 文件句柄是一个迭代器, 他的特点就是每次循环只在内存中占一行的数据, 非常节省内存.
- f = open('测试', mode='r', encoding='utf-8')
- for line in f:
- print(line) # 去掉 \n 可以这样写: print(line.strip())
- # 这种方式就是在一行一行的进行读取, 它就执行了下边的功能
- '''
- print(f.readline())
- print(f.readline())
- print(f.readline())
- .......
- '''
- # 输出结果:
这是一行测试
A: 这是第二行
B: 这是第三行
C: 这是第几行
D: 这是我也不知道第几行
就这么地吧.
特别注意: 读完的文件一定必须要关闭
rb 模式
rb 模式: 以二进制格式打开一个文件用于只读. 文件指针将会放在文件的开头. 记住下面讲的也是一样, 带 b 的都是以二进制的格式操作文件, 他们主要是操作非文字文件: 图片, 音频, 视频等, 并且如果你要是带有 b 的模式操作文件, 那么不用声明编码方式.
- f1 = open('图片. jpeg', mode='rb')
- tu = f1.read()
- f1.close()
- print(tu)
- # 输出结果:
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00H\x00H\x00\x00\xff\xe1\x00\xb0Exif\x............ 后面还有. 老长老长了.. 此处省略了.
rb 模式也有 read read(n) readline(),readlines() for 循环这几种方法, 这里就不一一演示了.
文件操作的: 写
文件操作的写, 有四种模式 (w,wb,w+,w+b),w+ 和 w+b 不常用, wb 操作的是非文本的文件, 比如: 图片, 视频, 音频. 操作方法是: write('要写入的内容')
w 模式
如果文件不存在, 用 w 模式操作文件, 它会先创建文件, 然后写入内容.
- f = open('这是一个新创建的文件', encoding='utf-8', mode='w')
- f.write('果然是一个新创建的文件')
- f.close()
如果文件存在, 利用 w 模式操作文件, 先清空原文件内容, 在写入新内容.
- f = open('这是一个新创建的文件', encoding='utf-8', mode='w')
- f.write('这是清空后重新写入的内容')
- f.close()
wb 模式
wb 模式: 以二进制格式打开一个文件只用于写入. 如果该文件已存在则打开文件, 并从开头开始编辑, 即原有内容会被删除. 如果该文件不存在, 创建新文件. 一般用于非文本文件如: 图片, 音频, 视频等.
>> 举个例子 :
我先以 rb 的模式将一个图片的内容以 bytes 类型全部读取出来, 然后在以 wb 将全部读取出来的数据写入一个新文件, 这样我就完成了类似于一个图片复制的流程. 具体代码如下:
- # 第一步: 将原图片通过 rb 模式读取出来.
- f = open('图片. jpeg', mode='rb')
- content = f.read()
- f.close()
- # 第二步: 将读取出来的数据通过 wb 模式写入新文件.
- f1 = open('图片 1.jpeg', mode='wb')
- f1.write(content)
- f1.close()
文件操作的: 追加
就是在文件中追加内容. 这里也有四种文件分类主要四种模式: a,ab,a+,a+b, 我们只讲 a
a 模式
如果文件不存在, 利用 a 模式操作文件, 那么它会先创建文件, 然后写入内容.
- f = open('追加文本', encoding='utf-8', mode='a')
- f.write('这个文件是没有的, 我是新创建的')
- f.close()
如果文件存在, 利用 a 模式操作文件, 那么它会在文件的最后面追加内容.
- f = open('追加文本', encoding='utf-8', mode='a')
- f.write('这是己存在的文件, 我是新追加的内容')
- f.close()
文件操作的其它模式
咱们还有一种模式没有讲, 就是那种带 + 号的模式. 什么是带 + 的模式呢?+ 就是加一个功能. 比如刚才讲的 r 模式是只读模式, 在这种模式下, 文件句柄只能进行类似于 read 的这读的操作, 而不能进行 write 这种写的操作. 所以我们想让这个文件句柄既可以进行读的操作, 又可以进行写的操作, 那么这个如何做呢? 这就是接下来要说这样的模式: r+ 读写模式, w + 写读模式, a + 写读模式, r+b 以 bytes 类型的读写模式.........
在这里咱们只讲一种就是 r+, 其他的大同小异, 自己可以练练就行了.
#1. 打开文件的模式有 (默认为文本模式):
r, 只读模式 [默认模式, 文件必须存在, 不存在则抛出异常]
w, 只写模式 [不可读; 不存在则创建; 存在则清空内容]
a, 只追加写模式 [不可读; 不存在则创建; 存在则只追加内容]
- #2. 对于非文本文件, 我们只能使用 b 模式,"b" 表示以字节的方式操作 (而所有文件也都是以字节的形式存储的, 使用这种模式无需考虑文本文件的字符编码, 图片文件的 jgp 格式, 视频文件的 avi 格式)
- rb
- wb
- ab
注: 以 b 方式打开时, 读取到的内容是字节类型, 写入时也需要提供字节类型, 不能指定编码
#3,'+'模式 (就是增加了一个功能)
r+, 读写 [可读, 可写]
w+, 写读 [可写, 可读]
a+, 写读 [可写, 可读]
#4, 以 bytes 类型操作的读写, 写读, 写读模式
r+b, 读写 [可读, 可写]
w+b, 写读 [可写, 可读]
a+b, 写读 [可写, 可读]
r+ 模式 读并追加 顺序不能错
r+: 打开一个文件用于读写. 文件指针默认将会放在文件的开头.
- f = open('文件的读写. txt', encoding='utf-8', mode='r+')
- content = f.read()
- print(content)
- f.write('这是新写入的内容')
- f.close()
注意: 如果你在读写模式下, 先写后读, 那么文件就会出问题, 因为默认光标是在文件的最开始, 你要是先写, 则写入的内容会讲原内容覆盖掉, 直到覆盖到你写完的内容, 然后在后面开始读取.
小总结:
三个大方向:
读, 四种模式: r rb r+ r+b
写, 四种模式 : w,wb, w+,w+b
追加 四种模式: a, ab, a+,a+b
相应的功能:
对文件句柄的操作: read read(n) readline() readlines() write()
文件操作的其它功能
f.tell() 获取光标的位置 单位是: 字节
- f = open('测试', encoding='utf-8', mode='r')
- print(f.tell())
- content = f.read()
- print(f.tell())
- f.close()
- # 原文件内容
这是一行测试
A: 这是第二行
B: 这是第三行
C: 这是第几行
D: 这是我也不知道第几行
就这么地吧.
- # 输出结果:
- 0 # 开始的位置
- 122 # 结束的位置
f.seek() 调整光标的位置 (注意: 移动单位是 byte , 如果是 utf-8 的中文部分要是 3 的倍数)
- f = open('测试', encoding='utf-8', mode='r')
- f.seek(9)
- content = f.read()
- print(content)
- f.close()
- # 原文件内容
这是一行测试
A: 这是第二行
B: 这是第三行
C: 这是第几行
D: 这是我也不知道第几行
就这么地吧.
# 输出结果:
行测试
A: 这是第二行
B: 这是第三行
C: 这是第几行
D: 这是我也不知道第几行
就这么地吧.
f.flush() 强制刷新
- f = open('测试', encoding='utf-8', mode='w')
- f.write('fafdsfsfsadfsaf')
- f.flush()
- f.close()
打开文件的另一种方式 (常用的是这种)
with open() as ....
- # 优点 1: 不用手动关闭文件句柄
- # 利用 with 上下文管理这种方式, 它会自动关闭文件句柄.
- with open('测试', encoding='utf-8', mode='r') as f:
- print(f.read())
- # 优点 2: 可以加多个 open 操作
- # 一个 with 语句可以操作多个文件, 产生多个文件句柄.
- with open('测试', encoding='utf-8', mode='r') as f,\
- open('测试', encoding='utf-8', mode='w') as f1:
- print(f.read())
- f1.write('kckckckckckckkck')
这里要注意一个问题, 虽然使用 with 语句方式打开文件, 不用你手动关闭文件句柄, 比较省事儿, 但是依靠其自动关闭文件句柄, 是有一段时间的, 这个时间不固定, 所以这里就会产生问题, 如果你在 with 语句中通过 r 模式打开 t1 文件, 那么你在下面又以 a 模式打开 t1 文件, 此时有可能你第二次打开 t1 文件时, 第一次的文件句柄还没有关闭掉, 可能就会出现错误, 他的解决方式只能在你第二次打开此文件前, 手动关闭上一个文件句柄.
文件的修改
文件的数据是存放于硬盘上的, 因而只存在覆盖, 不存在修改这么一说, 我们平时看到的修改文件, 都是模拟出来的效果, 具体的说有两种实现方式:
文件操作改的流程:
1, 以读的模式打开原文件.
2, 以写的模式创建一个新文件.
3, 将原文件的内容读出来修改成新内容, 写入新文件.
4, 将原文件删除.
5, 将新文件重命名成原文件.
方式一: 将硬盘存放的该文件的内容全部加载到内存, 在内存中是可以修改的, 修改完毕后, 再由内存覆盖到硬盘 (Word,VIM,nodpad++ 等编辑器)
- import os # 调用系统模块
- with open('测试', encoding='utf-8') as f1,\
- open('测试. bak', encoding='utf-8',mode='w') as f2:
- old_content = f1.read() # 全部读入内存, 如果文件很大, 会卡死
- new_content = old_content.replace('文', 'wen') # 在内存中完成修改
- f2.write(new_content) # 一次性写入新文件
- os.remove('测试') # 删除原文件
- os.rename('测试. bak', '测试') # 将新建的文件重命名为原文件
- # 原文件内容
** 文件操作改的流程:**
1, 以读的模式打开原文件.
2, 以写的模式创建一个新文件.
3, 将原文件的内容读出来修改成新内容, 写入新文件.
4, 将原文件删除.
5, 将新文件重命名成原文件.
# 修改后的内容
**wen 件操作改的流程:**
1, 以读的模式打开原 wen 件.
2, 以写的模式创建一个新 wen 件.
3, 将原 wen 件的内容读出来修改成新内容, 写入新 wen 件.
4, 将原 wen 件删除.
5, 将新 wen 件重命名成原 wen 件.
方式二: 将硬盘存放的该文件的内容一行一行地读入内存, 修改完毕就写入新文件, 最后用新文件覆盖源文件 (这种是常用的)
- import os
- with open('测试', encoding='utf-8') as f1,\
- open('测试. bak', encoding='utf-8',mode='w') as f2:
- for line in f1: # 一行一行的改, 占内存少
- new_line = line.replace('wen', '文')
- f2.write(new_line)
- os.remove('测试')
- os.rename('测试. bak', '测试')
- # 原文件内容
**wen 件操作改的流程:**
1, 以读的模式打开原 wen 件.
2, 以写的模式创建一个新 wen 件.
3, 将原 wen 件的内容读出来修改成新内容, 写入新 wen 件.
4, 将原 wen 件删除.
5, 将新 wen 件重命名成原 wen 件.
# 修改后的内容
** 文件操作改的流程:**
1, 以读的模式打开原文件.
2, 以写的模式创建一个新文件.
3, 将原文件的内容读出来修改成新内容, 写入新文件.
4, 将原文件删除.
5, 将新文件重命名成原文件.
来源: https://www.cnblogs.com/guanshou/p/12075610.html