文件读写
一、文件基本操作
1.最基本操作(打开、读取、关闭)
右击属性获取:地址+文件名
文件编码改为utf-8:文件>另存为>编码
(1).绝对路径
f = open(r"C:\Users\lenovo\Desktop\a.txt", "r", encoding = "utf-8")
print(f.read())
f.close()
(2).相对路径
相对路径是将文件放在项目文件夹内
f = open(r"a.txt", "r", encoding = "utf-8")
print(f.read())
f.close()
(3).with
with open(r"a.txt", "r", encoding = "utf-8") as f:
print(f.read())
2.写入(write/writelines)
# write() : 写从光标到文件末尾
# writelines() : 写入字符串或者字符串序列(列表内元素也必须是str)
with open(r"a.txt", "w", encoding = "utf-8") as f: # 文件不存在,先新建再写入
f.write("雪")
with open(r"a.txt", "w", encoding = "utf-8") as f: # 文件存在,先清空再写入
f.write("雪")
f.writelines("dx\n") # 写入字符串
f.writelines(["zzh\n","zdzxh"]) # 写入字符串序列
**********************************************************************
\a.txt
雪dx
zzh
zdzxh
3.读取(read/readline/readlines)
# read() : 读取从光标到文件末尾
# readline() : 读一行,字符串形式
# readlines() : 列表形式,["第一行", "第二行",...]
(1).read()
with open(r"a.txt", "r", encoding = "utf-8") as f:
f.seek(0)
print(f.read())
print(type(f.read()))
**********************************************************************
雪dx
zzh
zdzxh
<class 'str'>
(2).readline()
with open(r"a.txt", "r", encoding = "utf-8") as f:
f.seek(0)
line = f.readline()
print(type(line))
while line:
print(line.strip())
line = f.readline()
**********************************************************************
<class 'str'>
雪dx
zzh
zdzxh
(3).readlines()
with open(r"a.txt", "r", encoding = "utf-8") as f:
f.seek(0)
print(f.readlines())
print(type(f.readlines()))
**********************************************************************
['雪dx\n', 'zzh\n', 'zdzxh']
<class 'list'>
4.查看与移动文件指针
tell()与seek()
# tell() : 以bytes为单位,从文件头到当前指针位置字节的个数
# 文件头为0,中文utf-8是三个字节(不可拆分输出),换行是两个字节,英文数字符号是一个字节
# seek() : 以bytes为单位,指针的偏移量
with open(r"a.txt", "r", encoding = "utf-8") as f:
f.seek(0)
print("1:", f.tell())
print(f.readline().strip())
print("2:", f.tell())
print(f.readline().strip())
print("3:", f.tell())
print(f.readline().strip())
f.seek(8)
print("4:", f.tell())
print(f.readline().strip())
**********************************************************************
1: 0
雪dx
2: 7
zzh
3: 12
zdzxh
4: 8
zh
5.r 和 w
(1).r 只读
# \b.txt: 雪
**********************************************************************
with open(r"b.txt", "r", encoding = "utf-8") as f:
print(f.tell())
print(f.read())
**********************************************************************
0
雪
(2).w 只写(文件不存在新建并写入,文件存在直接重写)
with open(r"b.txt", "w", encoding = "utf-8") as f:
f.write("dx")
**********************************************************************
# \b.txt:
dx
6.rb 和 wb (非文本的只读与只写)
# 原项目文件夹内只有1.png
**********************************************************************
img = ""
with open(r"1.png", "rb") as f:
img = f.read()
with open(r"img.png", "wb") as f:
f.write(img)
**********************************************************************
# 项目文件夹内出现与1.png图片一样的img.png
7.a 追加 (在文件末尾增加)
# 文件不存在,新建再写入;文件存在,追加
with open(r"b.txt", "a", encoding = "utf-8") as f:
f.write("zzh")
**********************************************************************
# \b.txt:
dxzzh
8.r+, w+, a+
# r+ : 读写,指针在文件开头
# w+ : 读写,文件不存在新建,存在覆盖
# a+ : 读写,文件不存在新建,存在追加
9.总结
模式 | 描述 |
---|---|
r | 以只读方式打开文件,文件的指针将会放在文件的开头,这是默认模式 |
rb | 以二进制格式打开一个文件用于只读,文件指针会放在文件的开头,这是默认模式,一般用于非文本文件如图片、音频等 |
r+ | 打开一个文件用于读写,文件指针将会放在文件的开头 |
rb+ | 以二进制格式打开一个文件用于读写,文件指针会放在文件的开头,一般用于非文本文件如图片、音频等 |
w | 打开一个文件只用于写入,如果该文件已存在则将其覆盖,如果该文件不存在,创建新文件 |
wb | 以二进制格式打开一个文件只用于写入,如果该文件已存在则将其覆盖,如果该文件不存在,创建新文件,一般用于非文本文件如图片、音频等 |
w+ | 打开一个文件用于读写,如果该文件已存在则将其覆盖,如果该文件不存在,创建新文件 |
wb+ | 以二进制格式打开一个文件用于读写,如果该文件已存在则将其覆盖,如果该文件不存在,创建新文件,一般用于非文本文件如图片、音频等 |
a | 打开一个文件用于追加,如果该文件已存在,文件指针将会放在文件的结尾,也就是说,新的内容将会被写入到已有内容之后,如果文件不存在,创建新文件进行写入 |
ab | 以二进制格式打开一个文件用于追加,如果该文件已存在,文件指针将会放在文件的结尾,也就是说,新的内容将会被写入到已有内容之后,如果文件不存在,创建新文件进行写入 |
a+ | 打开一个文件用于读写,如果该文件已存在,文件指针将会放在文件的结尾,文件打开时会是追加模式,如果文件不存在,创建新文件用于读写 |
ab+ | 以二进制格式打开一个文件用于追加,如果该文件已存在,文件指针将会放在文件的结尾,也就是说,新的内容将会被写入到已有内容之后,如果文件不存在,创建新文件进行写入 |
二、上下文管理
1.概念
(1). 使用with打开文件,能够自动关闭文件,不需要执行close方法
(2). __enter__
和 __exit__
__enter__
: 进入时需要执行的代码,相当于准备工作
__exit__
: 退出时需要执行的代码,相当于收尾工作
(3). with通过这两个方法可以方便的实现上下文管理,with会把 enter 的返回值赋值给 as 后的变量
2.上下文管理器
from datetime import datetime
class Runtime:
def __enter__(self):
self.starttime = datetime.now()
print("程序运行开始的时间:{}".format(self.starttime))
return self.starttime
def __exit__(self, exc_type, exc_val, exc_tb):
self.endtime = datetime.now()
self.runtime = self.endtime - self.starttime
print("程序运行结束的时间:{}".format(self.endtime))
print("程序运行的时间:{}".format(self.runtime))
run = Runtime()
with run as a: # 上下文管理器 # a是__enter__的返回值,with会把这个返回值通过as赋值给a
print("a:",a)
for i in range(100000):
type("hello")
**********************************************************************
程序运行开始的时间:2019-04-17 15:01:15.957310
a: 2019-04-17 15:01:15.957310
程序运行结束的时间:2019-04-17 15:01:15.992608
程序运行的时间:0:00:00.035298
三、IO流
概念 :IO代表输入输出,流代表数据的无结构化传递,IO流就是以流的方式进行输入输出
1.StringIO(字符流)
StringIO在内存中如同打开文件一样操作字符串,因此也有文件的很多方法
当创建的StringIO调用 close() 方法时,在内存中的数据会被丢失
import io
sio = io.StringIO() # 实例化,创建了一个对象,进行保存读取
sio.write("hello") # 写
print(type(sio)) # 字符流
print(sio.getvalue()) # 读
sio.close() # 关闭
**********************************************************************
<class '_io.StringIO'>
hello
2.BytesIO(字节流)
BytesIO 和 StringIO 类似,但是BytesIO操作的是 Bytes数据
import io
bio = io.BytesIO() # 实例化,创建了一个对象,进行保存读取
bio.write(b"hello") # 写
print(type(bio)) # 字节流
print(type(b"hello")) # 必须前面+ b
print(bio.getvalue()) # 读
bio.close() # 关闭
**********************************************************************
<class '_io.BytesIO'>
<class 'bytes'>
b'hello'