一、写文件write()
打开文件 open();
name = "巴啦啦-小魔仙" # 定义一个变量name
fileobj = open('school.txt', 'w') #使用open()函数打开一个原本不存在的的文件,
#‘w’覆盖原文件内容,将这个函数传递给变量fileobj
fileobj.write(name) # 再用write()方法,将变量name写入到fileobj
fileobj.close() # 使用close()关闭fileobj,避免占用资源
查看运行结果:
没有报错表示运行成功,‘w’会自动创建一个文件并将内容以覆盖的方式写入,但是你点开school.txt会发现,它是一串乱码,这是因为我们没有将它进行正确的编码;
(什么是覆盖?如果原文件中有内容,将内容清空后再写入新内容)
name = "巴啦啦-小魔仙"
fileobj = open('school.txt', 'wb') #注意使用encode()方法改变编码格式时要将‘w’改为‘wb’,
#‘b’表示二进制模式,再在写的时候使用encode进行编码;就不会出现乱码
fileobj.write(name.encode("utf-8"))
fileobj.close()
再进行查看可以发现,它是正常的中文输出:
name = "巴啦啦-小魔仙"
fileobj = open('school.txt', 'w')
fileobj.write(name)
print(name.encode('utf-8')) #我们以utf-8的格式打印变量name
fileobj.close()
发现它变成了下图所示的结果:以utf-8的格式将变量name进行编码;一个汉字等于三个字节;
字符串类型(str):在程序中用于表示文字信息,本质上是unicode编码中的二进制。
name = "小胖"
字节类型(bytes):可表示文字信息,本质上是utf-8/gbk等编码的二进制(对unicode进行压
缩,方便文件存储和网络传输。)
name = "小胖"
data = name.encode('utf-8')
print(data) # b'\xe6\xad\xa6\xe6\xb2\x9b\xe9\xbd\x90'
result = data.decode('utf-8')
print(result) # "小胖"
name = "小胖"
data = name.encode('utf-8') #encode()进行编码
print(data) # b'\xe6\xad\xa6\xe6\xb2\x9b\xe9\xbd\x90'
result = data.decode('utf-8') #dencode()进行解码
print(result) # "小胖"
否则引起乱码
with open()
之前对文件进行操作时,每次都要打开和关闭文件,比较繁琐且容易忘记关闭文件。 以后再进行文件操作时,推荐大家使用with上下文管理,它可以自动实现关闭文件。
with open("school.txt", mode='rb') as file_object:
data = file_object.read()
print(data)
将最上面的修改成with open()
name = "巴啦啦-小魔仙"
with open('newschool.txt', 'wb') as fobj:
fobj.write(name.encode('utf-8'))
可以看到效果一样并且代码更简洁;
二、读文件read()
读文本文件
# 1.打开文件
# - 路径:
# 相对路径:'info.txt'
# 绝对路径:'D:\pythonProject\python全栈开发
\09\files\info.txt'
# - 模式
# rb,表示读取文件原始的二进制(r, 读 read;b, 二进制 binary;)
# 1.打开文件
file_object = open('info.txt', mode='rb')
# 2.读取文件内容,并赋值给data
data = file_object.read()
# 3.关闭文件
file_object.close()
print(data) # b'lvpengfei123\n\xe6\xad\xa6\xe6\xb2\x9b\xe9\xbd\x90-123'
text = data.decode("utf-8")
print(text)
读图片等非文本内容文件。
file_object = open('a1.png', mode='rb')
data = file_object.read()
file_object.close()
print(data) #
\x91\xf6\xf2\x83\x8aQFfv\x8b7\xcc\xed\xc3}\x7fT\x9d{.3.\xf1{\x
e8\...
【注意事项:】
- 路径
- 相对路径,你的程序到底在哪里运行的?
- 绝对路径
# 1.打开文件
file_object = open('D:\pythonProject\python全栈开发
\09\files\info.txt', mode='rt', encoding='utf-8')
# 2.读取文件内容,并赋值给data
data = file_object.read()
# 3.关闭文件
file_object.close()
windows系统中写绝对路径容易出问题:
# file_object = open('C:\\new\\info.txt', mode='rt',
encoding='utf-8')
file_object = open(r'C:\new\info.txt', mode='rt',
encoding='utf-8')
data = file_object.read()
file_object.close()
print(data)
读文件时,文件不存在程序会报错。
read()
将‘wb’改为‘rb’
【rb,表示读取文件以二进制模式(r, 读 read;b, 二进制 binary;) 】
【file_object = open('info.txt', mode='rt', encoding='utf-8') ,默认为文本文件模式,写不写‘t’都行,‘r’是读模式,默认的,写不写都行】
fr = open('school.txt','rt')
print(fr.read())
fr.close()
fr = open('school.txt')
print(fr.read())
fr.close()
name = "巴啦啦-小魔仙"
with open('newschool.txt', 'rb') as rf:
print(rf.read().decode('utf-8')) # 用decode()解码成utf-8的形式
也就是你在打开文件的时候使用‘rb’模式打开,那么你在读取的时候就要使用decode()进行解码
三、文件打开模式
===============================================================Character Meaning--------- ---------------------------------------------------------------
'r' open for reading (default)
'w' open for writing, truncating the file first
'x' create a new file and open it for writing
'a' open for writing, appending to the end of the file if it exists
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
The default mode is 'rt' (open for reading text).
关于文件的打开模式常见应用有:
只读: r 、 rt 、 rb (用)
- 存在,读
- 不存在,报错
只写: w 、 wt 、 wb (用)
- 存在,清空再写
- 不存在,创建再写
只写: x 、 xt 、 xb(因为x是创建一个新文件,所以创建文件时这个文件必须不存在)
- 存在,报错
- 不存在,创建再写。
只写: a 、 at 、 ab 【尾部追加】(用)
- 存在,尾部追加。
- 不存在,创建再写。
注意:在a模式下,调用write在文件中写入内容时,永远只能将内容写入到尾 部,不会写到光标的位置。
读写r+、rt+、rb+,默认光标位置:起始位置
- (用+的时候文件必须存在,因为他的功能描述是”打开一个文件进行读和写“,是打开一个已经存在的文件,不然会报错)
文件不存在会进行报错;
先写再读;
fileobj = open("myfile.txt", mode="rt+")
fileobj.write("123456789")
print(fileobj.read())
fileobj.close()
第一次执行
第二次执行,写入一个比第一次内容长的内容
第三次执行,输入一个比原先内容短的;
【注意】
+是打开文件进行更新,如果多次执行同一个文件,它的内容是不变的,因为它还是相同的内容;除非写入的内容进行改变,才会进行内容的更新;
当你输入的内容比原先输入的内容长时,会进行覆盖,而上次的内容被覆盖了,就相当于不存在了,所以读不到内容;
当你输入的内容比原先输入的内容短时,新输入的内容有多长就会替换原先的内容的多长,而这时上次的内容还存在,只是被新内容替换了一部分,所以可以读取到上次剩下的内容;
fileobj = open("myfile.txt", "rt+")
print(fileobj.read())
fileobj.write("嗨啦啦啦啊水水\n")
# print(fileobj.read())
fileobj.close()
先读再写;
fileobj = open("myfile.txt", "rt+")
print(fileobj.read())
fileobj.write("嗨啦啦啦啊水水\n")
# print(fileobj.read())
fileobj.close()
此时文件未执行,文本文件里没有内容:
第一次执行文件;控制台没有输出任何内容;文本文件有内容写入;
第二次执行;控制台输出了一行内容;文本文件中再写入一行内容;
第三次执行文件;控制台输出了两行内容;文本文件中再写入一行内容;
【看到这里,可能有小伙伴会有疑问,为什么明明文本文件中有三行内容,为什么只读取了两行内容呢?
其实是因为它是先读取文件内容,再写入新的内容;
所以第一次执行py文件后,没有内容输出,因为此时读取的是空文本文件,在读取空文本文件之后,才给文本文件添加内容;
所以第二次执行py文件后,输出了第一次输入的文本文件内容,因为此时文本文件里已经有了第一次执行时输入的内容,在读取文本文件之后,再给文本文件添加内容;
所以第三次执行py文件后,输出了第一次和第二次输入的文本文件内容,因为此时文本文件里已经有了第一次执行时输入的内容和第一次执行时输入的内容,在读取文本文件之后,再给文本文件添加内容;
继续执行py文件道理同上!】
w+、wt+、wb+,默认光标位置:起始位置(清空文件)
file_object = open('myfile.txt', mode='wt+')
# 读取内容
data = file_object.read()
print(data)
# 写入内容
file_object.write("你好呀")
# 将光标位置重置起始
file_object.seek(0)
# 读取内容
data = file_object.read()
print(data)
如果不加seek(0)将光标位置重置起始,将读不到数据,因为写完内容后,光标是在内容之后,而光标之后是读不到数据的;
只有将光标位置重置至开头才可以读到数据;
x+、xt+、xb+,默认光标位置:起始位置(新文件)
a+、at+、ab+,默认光标位置:末尾
file_object = open('myfile.txt', mode='at+')
# 写入内容
file_object.write("小胖")
# 将光标位置重置起始
file_object.seek(0)
# 读取内容
data = file_object.read()
print(data)
file_object.close()
将py文件执行多次,会一直在文本文件末尾添加内容;当然也要使用seek()方法将光标重置;
多用户注册案例:
while True:
user = input("用户名:")
if user.upper() == "Q":
break
pwd = input("密码:")
data = "{}-{}\n".format(user, pwd)
file_object = open('files/account.txt', mode='a')
file_object.write(data)
file_object.close()
file_object = open('files/account.txt', mode='a')
while True:
user = input("用户名:")
if user.upper() == "Q":
break
pwd = input("密码:")
data = "{}-{}\n".format(user, pwd)
file_object.write(data)
file_object.close()
第二种代码更好,因为只用打开文件一次,完成写入操作,在指定条件下就可以关闭;
而第一种代码,不停的打开文件关闭文件,如果文件不大还好,一旦文件过大,将会非常卡顿;
四、常用功能
读n个字符(字节)
首先,info.txt文本文件中本来就有内容,内容为”小胖小胖“
f = open('info.txt', mode='r')
# 读1个字符
chunk1 = f.read(1)
chunk2 = f.read(2)
print(chunk1, chunk2)
f.close()
执行完py文件后,可以看到,第一次读取了”小“,第二次读取了”胖小“
这是为什么呢?这是因为第一次读取了一个字符后,光标就移动到第一个字符之后了,在读取内容,就是从第一个字符之后开始的;
readline,读一行
此时文件中有两行文件
f = open('info.txt', mode='r', encoding='utf-8')
v1 = f.readline()
print(v1)
v2 = f.readline()
print(v2)
f.close()
执行完py文件后,发现它是一行一行读取的;
readlines,读所有行,每行作为列表的一个元素
f = open('info.txt', mode='r')
data_list = f.readlines()
f.close()
print(data_list)
seek()移动光标位置(字节)
f = open('info.txt', mode='r+', encoding='utf-8')
# 移动到指定字节的位置
f.seek(3)
f.write("小胖")
f.close()
将光标移到第三个字符之后,写入”小胖“,但是一个中文字符等于三个字节,所以”小胖“替换了6个数字;
【在 Python 中,不同的字符所占的字节数不同,数字、英文字母、小数点、下划线以及空格,各占一个字节,而一个汉字可能占 2~4 个字节,具体占多少个,取决于采用的编码方式。 例如,汉字在 GBK/GB2312 编码中占用 2 个字节,而在 UTF-8 编码中一般占用 3 个字节。】
tell()获取当前光标位置
f = open('info.txt', mode='r', encoding='utf-8')
p1 = f.tell()
print(p1) # 0
print(f.read(3))
p2 = f.tell()
print(p2) # 9
f.close()
五、上下文管理
之前对文件进行操作时,每次都要打开和关闭文件,比较繁琐且容易忘记关闭文件。以后再进行文件操作时,推荐大家使用with上下文管理,它可以自动实现关闭文件。
with open("xxxx.txt", mode='rb') as file_object:
data = file_object.read()
print(data)
在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:
with open("xxxx.txt", mode='rb') as f1, open("xxxx.txt",mode='rb') as f2:
pass