Python-文件操作
文本文件和二进制文件
- 文本文件是基于字符编码的文件,每一个字符按照特定的编码方式(自己设定,如ASCII,UTF-8)存储。
- 二进制文件的编码是变长的,自己可以定义。
- 文本文件可以用文本编辑软件查看。二进制文件用户一般不能直接读懂它们,只有通过相应的软件才能将其显示出来。
- 缓存过程:在CPU操作文件过程中,通过缓存,以保证慢速的硬盘读写和快速CPU之间的速率匹配。
文件的基本操作
操作文件的分为以下几个步骤:
- 打开文件
- 读(将文件内容读入内存)、写(将内存内容写入文件)文件
- 关闭文件
open函数
- open() 函数负责打开文件,并返回文件对象。
- 如果文件不存在,访问模式是读时会报错。
- 如果文件不存在,访问模式是写时会先创建一个文件。
- 遇到中文时,需要指定encoding。
- 当读取文件时,读过一次后,管道中的内容就没了,再读需要重新再建立管道。
文件open语法
open(file:file_name, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
- file_name变量是文件名。
- mode决定了打开文件的模式:只读,写入,追加等。所有可取值见下表。这个参数是非强制的,默认文件访问模式为只读®。
- buffering缓存设置
- 如果buffering的值被设为0,就不会有缓存。
- 如果buffering的值取1,访问文件时会缓存行。
- 如果将buffering的值设为大于1的整数,表明了这就是的寄存区的缓冲大小。
- 如果取负值,缓存区的缓冲大小则为系统默认。
文件的访问模式
访问模式 | 说明 | 详述 |
---|---|---|
r | 以只读方式打开文件 | 文件的指针将会放在文件的开头。这是默认模式。 |
w | 打开一个文件只用于写入 | 如果该文件已存在则将其覆盖,如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加 | 如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入 |
rb | 以二进制格式打开一个文件用于只读 | 文件指针将会放在文件的开头。这是默认模式 |
wb | 以二进制格式打开一个文件只用于写入 | 如果该文件已存在则将其覆盖 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后 | 如果该文件不存在,创建新文件进行写入 |
r+ | 打开一个文件从头读写 | 文件指针将会放在文件的开头 |
w+ | 打开一个文件用于读写 | 如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 |
a+ | 打开一个文件用于追加读写 | 如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写 |
rb+ | 以二进制格式打开一个文件从头读写 | 文件指针将会放在文件的开头 |
wb+ | 以二进制格式打开一个文件用于读写 | 如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 |
ab+ | 以二进制格式打开一个文件用于追加读写 | 如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写 |
read方法
- read方法从一个打开的文件中读取一个字符串(返回字符串)。
- 字符串可以是二进制数据,而不是仅仅是文字。
- size参数是要从已打开文件中读取的字节计数。该方法从文件的开头开始读入,如果没有传入size,它会尝试尽可能多地读取更多的内容。
fileObject.read([size])
""" example.txt文件的内容
I love you
not for who you are
but for what I am
"""
fp = open("example.txt", "r")
msg = fp.read(9)
print(type(msg))
print(msg)
fp.close()
result:
<class 'str'>
I love yo
readline方法
- 可以一次读取一行内容。
- 方法执行后,会把指针移动到下一行,准备再次读取。
- size是从文件中读取的字节数。
- 返回从字符串中读取的字节。
fileObject.readline(size)
""" example.txt文件的内容
I love you
not for who you are
but for what I am
"""
fp = open("example.txt", "r")
msg = fp.readline(9)
print(type(msg))
print(msg)
fp.close()
result:
<class 'str'>
I love yo
# 读取整个文件的内容
fp = open("example.txt", "r")
while True:
line = fp.readline()
if line: #当不是结尾时,会有换行符\n,只有到结尾了才为""
print(line, end='')
else:
break
fp.close()
readlines方法
- readlines方法用于读取所有行,并返回列表。
- 该列表可以由 for… in … 结构进行处理。
- 其中每一行的数据为一个元素。
- 每一行的末尾有换行符,可以通过strip()方法去除。
fileObject.readlines( )
fp = open("example.txt", "r")
msg = fp.readlines()
print(type(msg))
print(msg)
fp.close()
list1 = [i.strip() for i in msg]
print(list1)
result:
<class 'list'>
['I love you\n', 'not for who you are\n', 'but for what I am']
['I love you', 'not for who you are', 'but for what I am']
write方法
- write() 方法用于向文件中写入指定字符串,返回的是写入的字符长度。
- 在文件关闭前或缓冲区刷新前,字符串内容存储在缓冲区中,在文件中是看不到写入的内容的。
- 如果文件打开模式带 b,那写入文件内容时,str (参数)要用 encode 方法转为 bytes 形式,否则报错:TypeError: a bytes-like object is required, not ‘str’。
fileObject.write( [ str ])
fp_write = open("test.txt", "w")
msg = """I love you
not for who you are
but for what I am"""
fp_write.write(msg)
fp_write.close()
fp_read = open("test.txt", "r")
msg = fp_read.readlines()
print(msg)
fp_read.close()
result:
['I love you\n', 'not for who you are\n', 'but for what I am']
writelines方法
- writelines() 方法用于向文件中写入一序列的字符串。
- 这一序列字符串可以是由迭代对象产生的,如一个字符串列表。
- 换行需要制定换行符 \n。
fileObject.writelines( [ str ])
fp_write = open("test.txt", "w")
msg = "I love you\nnot for who you are\nbut for what I am\n"
list1 = ["1---I love you\n", "2--not for who you are\n", "3--but for what I am"]
fp_write.writelines(msg)
fp_write.writelines(list1)
fp_write.close()
fp_read = open("test.txt", "r")
msg = fp_read.readlines()
print(msg)
fp_read.close()
result:
['I love you\n', 'not for who you are\n', 'but for what I am\n', '1---I love you\n', '2--not for who you are\n', '3--but for what I am']
tell方法
- tell() 方法返回文件的当前位置,即文件指针当前位置。
- tell() 方法返回值不一定跟file文件指针在文件中的实际位置对应(因为文本模式下回车换行符会被自动翻译)。
# 如果没有换行符,len(msg)的值会和fp_write.tell()的值一致,但是因为换行符做了自动翻译,故二者不相等。
fp_write = open("test.txt", "w")
print(fp_write.tell())
msg = """I love you
n"""
fp_write.write(msg)
print(len(msg), fp_write.tell())
fp_write.close()
result:
0
12 13
seek方法
- Seek方法改变当前文件的位置。
- Offset变量表示要移动的字节数。
- 如果操作成功,则返回新的文件位置,如果操作失败,则函数返回 -1。
- whence变量指定开始移动字节的参考位置。
- whence = 0,将文件的开头作为移动字节的参考位置。
- whence = 1,则使用当前的位置作为参考位置。
- whence = 2,则使用该文件的末尾将作为参考位置。
seek(self, offset, whence=0)
# test.txt文件找那个的内容
"I love you not for who you are"
fp_read = open("test.txt", "r")
for i in range(5):
position = fp_read.seek(i, 0)
data = fp_read.read(1)
print(f"Loop:{i:<10} position:{position:<10} data:{data}")
fp_read.close()
result:
Loop:0 position:0 data:I
Loop:1 position:1 data:
Loop:2 position:2 data:l
Loop:3 position:3 data:o
Loop:4 position:4 data:v
flush方法
- 一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。
- flush() 方法是用来刷新缓冲区的,将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要被动的等待输出缓冲区写入。
# 无参数,无返回值
fileObject.flush()
# 如果没有fp_write.flush()语句,在fp_write.close()之前是看不到文件写入的内容的。而有了之后,在fp_write.close()之前缓冲区的内容已经写入文件,可以看到。
fp_write = open("test.txt", "w")
msg = "I love you\nnot for who you are\nbut for what I am\n"
fp_write.writelines(msg)
fp_write.flush()
fp_write.close()
close方法
- close() 方法用于关闭一个已打开的文件。关闭后的文件不能再进行读写操作, 否则会触发 ValueError 错误。close() 方法允许调用多次。
- 当file对象,被引用到操作另外一个文件时,Python 会自动关闭之前的 file 对象。 使用 close() 方法关闭文件是一个好的习惯。
- 该方法没有返回值。
fileObject.close()
打开关闭操作
传统方法
- open和close语句单独写。
with…as…方法
- 只需要一个语句,实现了打开和最后的自动关闭。
with open(文件名, 模式) as 文件对象:
文件对象.方法()
...
二者比较
-
传统文件读写,容易犯的问题
- 忘记 ‘关闭文件’
- 文件读写 ‘异常’ 时,未做处理
-
with as 读写文件
- 自动处理上述问题
- 语句简洁
文件操作举例
文件复制
sour_name = "chenxiao.jpg"
targ_name = "boy.jpg"
with open(sour_name, "rb") as f_sour:
data = f_sour.readlines()
with open(targ_name, "wb") as f_targ:
f_targ.writelines(data)
#复制完之后再最后加上一句话
sour_name = "test.txt"
targ_name = "test2.txt"
with open(sour_name, "r", encoding="utf-8") as f_sour:
data = f_sour.read()
with open(targ_name, "w", encoding="utf-8") as f_targ:
f_targ.write(data)
f_targ.write("\n这是复制文件")