一、文件操作概述
1). 文件操作注意事项
- 如果不指定编码方式,python以文本方式读取文件的时候会使用当前操作系统默认的编码方式读写文件。
- linux/Mac OS 为"utf8"
- windows 为 "gbk"
- python3默认是"utf8",在windows平台如果以文本方式读写文件不指定编码方式会发生编码错误!
2). open函数-操作文件
- 默认打开方式为文本方式
- 第一个参数为文件路径
- 第二个参数为文件操作模式:t代表文本方式,可以不写(一般不写);r代表只读
- 第三个参数指定编码方式
- open函数返回值为文件句柄
f = open('a.txt','rt',encoding="utf8")
encoding_way = f.encoding # 查看读取文件的编码方式
texts = f.read() # 全量读取
f.close() # 释放资源
3).文件操作模式介绍
- 操作模式对应open函数的第二个参数
- 只存在如下的模式, (例如
wr
就是非法的)
读 | 写 | 追加 |
---|---|---|
只读 r | 只写 w | 追加 a |
读写 r+ | 写读 w+ | 追加读写 a+ |
二进制读 rb | 二进制写 wb | 二进制追加 ab |
二进制读写 rb+ | 二进制读写 wb+ | 二进制追加读写 ab+ |
上述文本文件的模式省略了
t
4). with语法
-
with块结束会自动释放资源,可以省略
f.close()
-
语法格式
with open(filename, [operation_model], [charset]) as f:
pass
with open('a.txt','w') as f:
f.write('1111\n')
- with关键字同时打开多个文件
-
\
为python中代码换行的标志
-
with open('test.txt','r',encoding='gbk') as src_f,\
open('xxx_new','w',encoding='gbk') as dst_f:
data=src_f.read()
dst_f.write(data)
5). chardet
- 第三方智能检测字符编码工具chardet,能最大限度的识别字符的编码方式
- 需要在线安装对应模块
pip install chardet
- 使用方式
result = chardet.detect(open("log",mode="rb").read())
print(result)
6). 判断文件是否关闭了
f = open('test.txt','r',encoding='utf-8')
print(f.closed)
f.close()
7). 查看打开文件所用的编码方式
with open('test.txt','r') as f:
print(f.encoding)
7). 针对写操作:刷新,将内存里面的东西保存在文件中
with open("test.txt","ab+") as f:
data = b"adfaeadfjiefka" # 这种方式为转换为byte类型
f.write(data)
f.flush() # 刷新
二、文本文件
- 演示文件
a.txt
this is line 1
this is line 2
this is line 3
this is line 4
this is line 5
this is line 6
this is line 7
this is line 8
this is line 9
1). 文本只读
- 不指定操作模式,默认文本只读
f = open("a.txt", encoding="utf-8")
- 指定文本只读操作
f = open("test.txt", "r", encoding="utf8")
# 每读取一定数据,游标就移动到相应的位置
charge = f.readable() # 判断文件是否可读
a = f.read() # 一次性读取所有数据
b = f.readline() # 读取一行信息
c = f.readlines() # 将所有的内容弄成一个列表,每行的内容为一个元素
f.close() # 使用完毕要关闭文件句柄,释放系统资源
- 以字符个数为单位读取文件
with open("test.txt","r") as f:
print(f.read(4))
2). 文本只写
-
w
模式会将存在的文件清空 (很危险,慎重使用!) 再操作,不存在就新建!
with open('test.txt','w',encoding='utf8') as f:
print(f.writable()) # 判断是否可写
f.write('11111111\n')
f.writelines(['555\n','6666\n']) # 参数是一个列表,列表里面的元素只能为字符串
3). 文本只追加
with open('test.txt','a',encoding='utf-8') as f: # 追加方式,游标直接指向末尾
f.write('我写到文件最后')
4). +文本模式操作
-
r+
:读写操作,打开时游标指向开头,此时内容没有被清空
with open('test.txt','r+',encoding='utf-8') as f:
f.write('123sb') # 打开后直接写,指针指向开头,会覆盖原来的对应字节的内容
print(f.read())
f.write('123sb') # 经过读操作,指针指向了末尾,写为追加到最后
-
w+
:先清空文件内容,然后后操作
with open('test.txt','w+',encoding='utf-8') as f:
f.write("abcdefg")
-
a+
:追加读写,游标默认在文件尾
with open('test.txt','a+',encoding='utf-8') as f:
f.write("dfadf sdafa")
5). 获取操作系统的换行符
- open函数第三个参数如果设置为
newline=''
,读取之后将换行符换成宿主机上的换行符- 相互转换:win
\r\n
<---> unix\linux\n
- 相互转换:win
with open('test.txt','r',encoding='utf-8',newline='') as f:
data = f.read().encode("utf-8")
print(data)
三、二进制读写追加文件
1). 二进制操作概述
- binary操作模式不能指定字符编码,因为是二进制,所以不需要编码
- window平台回车是
\r\n
;unix、linux 为\n
-
\x
开头表示为十六进制 - 编码解码的关系
- '字符串'(Unicode) ---------encode---------> bytes
- '字符串'(Unicode) <--------decode---------- bytes
- Python中表示二进制 (不能有中文,只能为ASCII)
byte_ = b"abc123"
print(byte_)
2). 以二进制读文件,然后进行解码
with open('test.txt','rb') as f:
data = f.read()
print(data)
print(data.decode('utf-8'))
3). 二进制方式写文件,指定转换为对应编码的二进制
- 注意:
w
操作会将文件清空!
with open('test.txt','wb') as f:
f.write(bytes('1111\n', encoding='utf-8'))
f.write('杨件'.encode('utf-8'))
4). 二进制方式追加,将内容编码后追加到文件最后
with open('test22.py','ab') as f:
f.write('杨件'.encode('utf-8'))
5). 不知道编码的情况下,latin-1会尽可能多的还原
with open('test.txt','r+',encoding='latin-1') as f:
data=f.read()
print(data)
f.write('aaaaaaaaaaa')
四、游标操作
1). 游标操作说明
- 文本文件与二进制文件均可使用游标操作
2). 常见操作
-
f.tell()
获取当前游标的位置,以字节 (1byte = 8bit) 为单位
with open("test.txt","rb") as f:
f.readline()
print(f.tell())
-
f.seek()
移动游标 (字节为单位)
with open("test.txt","rb+") as f:
f.readline()
f.seek(3) # 相对于0的位置进行移动
f.seek(10, 1) # 参数1: 相对于上一次光标移动的位置,byte的方式,可正可负
f.seek(-5, 2) # 相对于文件末尾,参数2,第一个参数必须为负数
print(f.read().decode('utf8'))
-
f.truncate(n)
以字节为单位截取文件- 必须存在写模式才能如此操作
with open("test.txt","rb+") as f:
f.truncate(3)
3). 读取文本大文件最后一行的推荐方法
offset = -4
data_lis = None
with open("test.txt" ,"rb") as f:
while True:
f.seek(offset, 2)
data_lis = f.readlines()
if len(data_lis) > 1:
break
else:
offset *= 2
print(data_lis[1].decode("utf8"))
网友评论