Python 之文件处理open功能——模式介绍
文件是操作系统提供给用户/应用程序操作硬盘的一种虚拟的概念/接口。 用户/应用程序可以通过文件将数据永久保存的硬盘中,即操作文件就是操作硬盘。
用户/应用程序直接操作的是文件,对文件进行的所有操作都是在向操作系统发送系统调用,然后再由操作将其转换成具体的硬盘操作
open()功能使用的模块
t文本模块(默认)、x只写模式、b二进制模式,r只读模式,w只写模式,a只追加模式,+模式 控制文件读写内容的模式,t和b模式不能单独使用,必须跟r,w,a连用
t 文本模式(默认)
文本模式读写都是以str(unicode)为单位 必须是文本文件 必须指定字符编码 encoding=‘utf-8’ t模式会将f.read()读出的结果解码成unicode #没有指定encoding参数操作系统会使用自己默认的编码,LInux系统默认utf-8,Windows系统默认gbk with open('a.txt',mode='rt',encoding='utf-8') as f: ###指定编码 rt:硬盘的二进制读入内存 >> t模式会将读入内存的内容进行decoding解码操作 rb: 硬盘的二进制读入内存 >> b模式下,不做任何转换,直接读入内存
t和b模式总结
1.在操作纯文本文件方面,t模式省去了编码和解码环节,b模式则需要手动编码和解码 2.在针对非文本文件(如:图片,视频,音频等)只能使用b模式
x只写模式
x只写模式,不可读:文件不存在创建,文件存在报错
>>> with open('g.txt',mode='x',encoding='utf-8') as f:
f.read()
>>> with open('a.txt',mode='x',encoding='utf-8') as f:
f.write('aaabbc')
# cat a.txt
aaabbc
b二进制模式
内存: utf-8格式的二进制 >> 解码 >> unicode 硬盘: (c.txt内容:utf-8格式的二进制) bytes类型 >> 当成二进制 得到bytes类型的三种方式: 1.字符串编码之后的结果 2.b'纯英文字符' 3.b模式下打开文件,f.read()读出内容 rb: 硬盘的二进制读入内存 >> b模式下,不做任何转换,直接读入内存 1.读写都是以bytes为单位 2.可以针对所有文件 3.一定不能指定字符编码,即一定不能指定encoding参数
>>> with open(r'g.txt',mode='rb') as f:
res=f.read()
print(res)
b'111\n222\n333\n444\n555\n'
#将二进制文件转换为utf-8
>>> with open(r'g.txt',mode='rb') as f:
res=f.read()
print(res,type(res))
print(res.decode('utf-8'))
print(res,type(res))
>>> with open(r'g.txt',mode='wb') as f:
... f.write('aaa')
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: a bytes-like object is required, not 'str'
>>> with open(r'g.txt',mode='wb') as f:
f.write('你好'.encode('utf-8'))
f.write('你好'.encode('gbk')) #双编码会出现部分识别,部分乱码
----------------- # 拷贝工具【文本,图片,视频】---------------
#!/bin/python3
# -*- coding: utf-8 -*-
src_file=input('源文件路径:').strip()
dst_file=input('源文件路径:').strip()
with open(r'{}'.format(src_file),mode='rb') as f1,\
open(r'{}'.format(dst_file),mode='wb') as f2:
#res=f1.read() #文件过大时,会造成内存占用过大
#f2.write(res)
for line in f1:
f2.write(line)
# python3 r4.py
源文件路径:g.jpg
源文件路径:d.jpg
--------------# 当文件过大过长会占用较大内存,需要循环去读
#循环读取文件
#方式一: while 适用于文件较大,一行较长,自己控制每次读取文件的数据的数据量
with open(r'g.jpg',mode='rb') as f:
while res:
res=f.read(1024)
if not res:
break
print(len(res))
with open(r'g.jpg',mode='rb') as f:
while True:
res=f.read(1024)
if len(res) == 0:
break
print(len(res))
#方式二:for 以行为单位读,当一行内容过长时会导致一次读入内容的数据量过大
--------# rt
with open(r'g.txt',mode='rt',encoding='utf-8') as f:
for line in f:
print(line)
你好
---------# rb
with open(r'g.jpg',mode='rb') as f:
for line in f:
print(line)
b'\xe4\xbd\xa0\xe5\xa5\xbd\n'
b'\xe4\xb8\xad\xe5\x8d\x8e\n'
b'88\n'
r只读模式
以t模式为基础进行内存操作: r,w,a r默认的操作模式: 只读模式,当文件不存在时报错,当文件存在时,文件指针跳到开始位置
with open('a.txt',mode='rt',encoding='utf-8') as f:
l=f.read() #把所有内容从硬盘读入内存
print(l)
with open('a.txt',mode='rt',encoding='utf-8') as f: #未添加此行则下面不会打印,文件指针未跳转,文件有换行则输出也会有换行
l2=f.read() #把所有内容从硬盘读入内存
print(l2)
-------
# cat user.txt
wei:123
# cat r.py
#!/bin/python3
# -*- coding: utf-8 -*-
inp_username=input('you name:').strip()
inp_password=input('you password:').strip()
with open('user.txt',mode='rt',encoding='utf-8') as f:
res=f.read()
username,password=res.strip().split(':')
if inp_username == username and inp_password == password:
print('login successfull')
else:
print('username or password error')
# python3 r.py
you name:wei
you password:123
login successfull
-------------------------------------------
# cat r1.py
#!/bin/python2
# -*- coding: utf-8 -*-
with open('user.txt',mode='rt',encoding='utf-8') as f:
for line in f:
print(line,end='')
# python3 r1.py
wei:123
li:111
zhang:222
wang:333
-------------------------###根据文件账户密码进行查询,登录实例---------------------
# cat user.txt
wei:123
li:111
wang:222
zhang:333
# cat r1.py
#!/bin/python3
# -*- coding: utf-8 -*-
inp_username=input('you name:').strip()
inp_password=input('you password:').strip()
with open('user.txt',mode='rt',encoding='utf-8') as f:
for line in f:
#print(line,end='') #wei:wei\n
username,password=line.strip().split(':')
if inp_username == username and inp_password == password:
print('login successfull')
break
else:
print('username or password error')
# python3 r1.py
you name:wei
you password:123
login successfull
# python3 r1.py
you name:li
you password:111
login successfull
# python3 r1.py
you name:wang
you password:222
login successfull
# python3 r1.py
you name:zhang
you password:333
login successfull
----------------------------------------------------------
# cat user.txt
wei:123
li:111
wang:222
zhang:333
# python3 r1.py
#!/bin/python3
# -*- coding: utf-8 -*-
name=True
while name:
inp_username=input('you name:').strip()
inp_password=input('you password:').strip()
with open('user.txt',mode='rt',encoding='utf-8') as f:
for line in f:
#print(line,end='') #wei:wei\n
username,password=line.strip().split(':')
if inp_username == username and inp_password == password:
print('login successfull')
name=False
break
else:
print('username or password error')
# python3 r1.py
you name:wei
you password:121
username or password error
you name:wei
you password:123
login successfull
w只写模式
w只写模式,当文件不存在时,会创建空文件,当文件存在时会w会清空文件,指针位于开始位置,w模式打开就会被清空再把后面写入内容覆盖进去
w模式创建新文件: 1.在以w模式打开文件,没有关闭的情况下,连续的写入,新的内容总是跟在旧的内容之后 2.如果重新以w模式打开文件则会清空文件
with open('a.txt',mode='wt',encoding='utf-8') as f:
f.read() #文件不可读
f.write('ojbk\n') #向文件写入ojbk
f.write('ojbk\n')
f.write('ojbk\n') #在以w模式打开文件没有关闭的情况下,连续的写入,新的内容总是跟在旧的之后
--------# 文件的copy工具【文本】-----------------
# cat r3.py
#!/bin/python3
# -*- coding: utf-8 -*-
with open('a.txt',mode='rt',encoding='utf-8') as f1,\
open('e.txt',mode='wt',encoding='utf-8') as f2:
res=f1.read()
f2.write(res)
# cat a.txt
zhongguo
中华
# python3 r3.py
# cat e.txt
zhongguo
中华
-------------------------------------
# cat r3.py
#!/bin/python3
# -*- coding: utf-8 -*-
src_file=input('源文件路径:').strip()
dst_file=input('源文件路径:').strip()
with open(r'{}'.format(src_file),mode='rt',encoding='utf-8') as f1,\
open(r'{}'.format(dst_file),mode='wt',encoding='utf-8') as f2:
res=f1.read()
f2.write(res)
# cat a.txt
zhongguo
中华
# python3 r3.py
源文件路径:a.txt
源文件路径:c.txt
# cat c.txt
zhongguo
中华
a只追加模式
a只追加写,在文件不存在的时候会创建空间文件,在文件存在时文件指针会直接跳到末尾 a模式用来在原有的文件内存的基础上写入新的内容,如:记录日志,注册等
with open('a.txt',mode='at',encoding='utf-8') as f:
f.read() #报错不能读
f.write('aaa') #可以写入,连续写入
#a模式用来在原有的文件内存的基础上写入新的内容,如记录日志,注册
-----------实现注册功能----------------------
# cat r2.py
#!/bin/python3
# -*- coding: utf-8 -*-
name=input('you name:').strip()
pwd=input('you password:').strip()
with open('db.txt',mode='at',encoding='utf-8') as f:
f.write('{}:{}\n'.format(name,pwd))
# python3 r2.py
you name:wei
you password:123
# python3 r2.py
you name:wang
you password:222
# cat db.txt
wei:123
wang:222
w与a模式异同
相同点: 在打开的文件不关闭的情况下,连续的写入,新写的内容总会跟在前写的内容后
不同点:
a模式重新打开文件不会清空原文件内容,会将文件指针直接移动到文件末尾新写内容, w模式重新打开文件会清空原文件内容 w模式用于:创建新文件,记录日志 a模式用于:针对老文件【日志,记录等】
+模式
+可读可写,+不能单独使用,必须配合r,w,a r+t: 文件不存在直接报错 w+t: 文件不存在直接创建 a+t: 文件追加进去
############### r+t
>>> with open('g.txt',mode='r+t',encoding='utf-8') as f:
#print(f.read()) #文件不存在会报错
f.write('aaa') #内容写到开头,若是前面有打印输出会在后面追加
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'g.txt'
>>> with open('g.txt',mode='w+t',encoding='utf-8') as f:
...
>>> with open('g.txt',mode='a+t',encoding='utf-8') as f:
...
>>> with open('t.txt',mode='a+t',encoding='utf-8') as f:
############### w+t
>>> with open('g.txt',mode='w+t',encoding='utf-8') as f:
print(f.read()) #文件不存在不会报错,会创建
>>> with open('g.txt',mode='w+t',encoding='utf-8') as f:
f.write('111\n')
f.write('222\n')
f.write('333\n')
print('====>',f.read())
# cat g.txt
111
222
333
############### a+t
>>> with open('g.txt',mode='a+t',encoding='utf-8') as f:
print(f.read()) #文件读不出来
f.write('444\n') #文件写入
f.write('555\n')
print(f.read()) #文件读不出来
# cat g.txt
111
222
333
444
555
控制文件指针移动 seek
指针移动的单位都是以bytes/字节为单位 只有一种情况: t模式的read(n),n代表的是字符个数 seek移动字节指针,tell文件指针当前位置 只有0模式可以在t模式下使用,1,2模式必须在b模式下使用
seek(n,模式)模式:
模式0: 参照物是文件开头位置
模式1: 参照物是当前指针所在位置
模式2:参照物是文件末尾位置,应该倒着移动
# cat g.txt
abc你我他
>>> with open('g.txt',mode='rt',encoding='utf-8') as f:
res=f.read(4)
print(res)
abc你
f.seek(9,0)
f.seek(3,0) #3
f.seek(9,1)
f.seek(3,1) #12
f.seek(-9,2) #3
f.seek(-3,2) #9
#f.tell #获取文件指针当前位置
>>> with open('g.txt',mode='rt',encoding='utf-8') as f:
f.seek(2,0)
--------------------# 案例
>>> with open('g.txt',mode='rb') as f:
f.seek(9,0)
f.seek(3,0)
print(f.tell())
9
3
3
>>> with open('g.txt',mode='rb') as f:
f.seek(9,0)
f.seek(3,0)
res=f.read()
print(res.decode('utf-8'))
9
3
你我他
>>> with open('g.txt',mode='rb') as f:
f.seek(9,1)
f.seek(3,1)
print(f.tell())
9
12
12
>>> with open('g.txt',mode='rb') as f:
f.seek(9,1)
f.seek(3,1)
res=f.read()
print(res.decode('utf-8'))
9
12
>>> with open('g.txt',mode='rb') as f:
f.seek(-9,2)
f.seek(-3,2)
print(f.tell())
4
10
10
# cat g.txt
aasdasdasdas
>>> with open('g.txt',mode='rb') as f:
f.seek(-9,2)
f.seek(-3,2)
print(f.read().decode('utf-8'))
4
10
as
#!/bin/python3
# -*- coding: utf-8 -*-
with open('g.txt',mode='rt',encoding='utf-8') as f:
for line in f:
print(line.strip())
while True:
line=f.read(1024)
print(line.strip())
if len(line) == 0:
break
----------------------# f.seek实现tail功能
# cat r6.py
#!/bin/python3
# -*- coding: utf-8 -*-
import time
with open('access.log',mode='rb') as f:
#1.将指针跳到文件末尾
#f.read() 错误写法,文件较大会有内存溢出
f.seek(0,2)
while True:
line=f.readline()
if len(line) == 0:
time.sleep(0.3)
else:
print(line.decode('utf-8'))
写入文件追加
# cat a.py
#!/bin/python3
# -*- coding: utf-8 -*-
with open ('access.log',mode='at',encoding='utf-8') as f:
f.write('20220503 wei')
# python3 a.py
# python3 a.py
# python3 r6.py #实现tail追加显示文件内容
20220503 wei
20220503 wei