文件操作及相关函数


文件操作

文件操作流程

文件以什么编码存储的,就以什么编码打开
参数:

1.文件路径

2.编码方式,encode

3.执行动作(打开方式):只读,只写,追加,读写,写读…
例如:

打开一个已经存在的文件

f = open('D:\qycache\飞碟说.txt',encoding='utf-8',mode='r')
content = f.read()
print(content)
f.close()

# 输出:只是从未如此性感

代码解释:
f 变量,可以命名为f_obj,file,f_handler等,这个变量称之为文件句柄(句柄是操作系统在生成对象时分配给对象的唯一标识)

open windows的系统功能,也就是说open这个命令,其实就是调用系统打开文件的动作

windows 默认的编码方式:gbk,linux默认的编码方式为utf-8

f.close() 关闭文件
所以文件操作的流程是这样的:打开一个文件,产生一个文件句柄,对文件句柄进行操作,关闭文件

# 一.文件的写入
# 1.打开文件
fp = open("ceshi1.txt",mode="w",encoding="utf-8") # 把冰箱门打开
# 2.写入内容
fp.write("把大象塞进去") # 把大象放进去
# 3.关闭文件
fp.close() # 把冰箱门关上
# 二.文件的读取
# 1.打开文件
fp = open("ceshi1.txt",mode="r",encoding="utf-8") #1.打开冰箱门
# 2.读取内容
res = fp.read() # 把大象拿出来
print(res)
# 3.关闭文件
fp.close() # 把冰箱门关上

文件的操作模式

w		 write 写入模式
		 文件不存在则创建文件,存在的话则打开清空内容,
		 并且将文件指针放在文件的开头

r		 read 读取模式
		 文件不存在则报错,存在的话则打开文件,并且将文
		 件指针放在文件的开头
				
a		append 读取模式
		文件不存在则创建文件,存在的话则打开文件,并且
		将文件的指针放在文件的末尾
		扩展模式(配合打开模式的辅助模式,自己单独不能使用)
				
+		plus	增强模式(可以让文件具有读写功能)

b		bytes	bytes模式(二进制字节流)
		模式一共16种:
		
w		写入			     w+	    以读写模式打开

wb		以二进制写模式打开	 wb+    以二进制读写模式打开

r		读取			     r+	    以读写模式打开

rb		以二进制读模式打开	 rb+	以二进制读写模式打开

a		以追加模式打开		 a+	    以读写模式打开

ab		以二进制追加模式打开	 ab+	以二进制读写模式打开

字节流(bytes)

字节---->bytes---->是用来传输或者存储的数据格式
例如:b'1234' b"abcd",范围只能是ascii编码
形如b"我爱你",这种b后面带中文的,是不可以的
如果是中文使用encode 和 decode 来进行转换;
将字符串和字节流(Bytes流)类型进行转换 (参数写成转化的字符编码格式)
encode() 编码 将字符串转化为字节流(Bytes流)
decode() 解码 将Bytes流转化为字符串
strvar = "我爱你"
# encode 编码 -> 变成二进制字节流
res = strvar.encode("utf-8")
print(res , type(res)) # b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0' <class 'bytes'>

# decode 解码 =>二进制字节流恢复成原来的字符串
res2 = res.decode("utf-8")
print(res2 , type(res2)) # 我爱你 <class 'str'>

存储二进制字节流

# 存储二进制字节流
"""不需要指定encoding编码集,否则报错"""
fp = open("ceshi2.txt",mode="wb")
fp.write(strvar)
fp.close()

读取二进制字节流

# 读取二进制字节流
fp = open("ceshi2.txt",mode="rb")
res = fp.read()
fp.close()
print(res) # b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'
# 通过decode反解出字符串
strvar = res.decode()
print(strvar) # 我爱你

复制图片也是要用到rb和wb的

# 复制图片
"""图片,音频,视频"""
# 1.读取原图片所有的内容
fp = open("集合.png",mode="rb")
res = fp.read()
fp.close() 

# 2.把读取的内容存储到另外一个文件
# fp = open("集合2.png",mode="wb")
# 指定绝对路径(完整路径)
fp = open(r"E:\python31\day8\集合3.png",mode="wb")
fp.write(res)
fp.close()

读取文件的五种方式

1.read() 将文件的内容全部读取出来, 弊端: 占内存, 如果文件过大,容易导致内存崩溃

f = open("../def/哇擦.txt", mode="r", encoding="utf-8")
content = f.read()
print(content)

结果:
友谊地久天⻓,
爱⼀点,
可惜我是⽔瓶座
⼀⽣中最爱

2.read(n) 读取n个字符. 需要注意的是. 如果再次读取. 那么会在当前位置继续去读⽽不是从头读, 如果使⽤的是rb模式. 则读取出来的是n个字节

f = open("../def/哇擦.txt", mode="r" encoding="utf-8")
content = f.read(3)
print(content)
结果:
友谊地
f = open("../def/哇擦.txt", mode="rb")
content = f.read(3)
print(content)
结果:
b'\xe5\x8f\x8b'
f = open("../def/哇擦.txt", mode="r", encoding="utf-8")
content = f.read(3)
content2 = f.read(3)
print(content)
print(content2)
结果:
友谊地
久天⻓

3.readline() 一次读取一行数据, 注意: readline()结尾, 注意每次读取出来的数据都会有一个\n 所以呢. 需要我们使用strip()方法来去掉\n或者空格

with open("F:\python_sy\爱.txt",mode="r+",encoding="utf-8") as fp:
    a = fp.readline()
    a1 = fp.readline()
    a2 = fp.readline()
    a3 = fp.readline()
    fp.close()

print(a.strip())
print(a1.strip())
print(a2.strip())
print(a3.strip())

# 输出:
'''
所爱
隔山海。
山海,
皆可平。我爱你
'''

4.readlines()将每一行形成一个元素, 放到一个列表中. 将所有的内容都读取出来. 所以也是. 容易出现内存崩溃的问题.不推荐使用

f = open("../def/哇擦.txt", mode="r", encoding="utf-8")
lst = f.readlines()
print(lst)
for line in lst:
 print(line.strip())

5.循环读取. 这种方式是组好的. 每次读取一行内容.不会产生内存溢出的问题.(推荐)

f = open("../def/哇擦.txt", mode="r", encoding="utf-8")
for line in f:
 print(line.strip())

注意: 读取完的文件句柄一定要关闭 f.close()

只读(r , rb)

f = open("少妇嫩模.txt",mode="r", encoding="utf-8")
content = f.read()
print(content)
f.close()

需要注意encoding表示编码集. 根据文件的实际保存编码进行获取数据, 对于我们而言. 更多的是utf-8.
rb. 读取出来的数据是bytes类型, 在rb模式下. 不能选择encoding字符集.

f = open("少妇嫩模.txt",mode="rb" )
content = f.read()
print(content)
f.close() 
结果:
b'\xe6\xaf\x85\xe5\x93\xa5, \xe5\xa4\xaa\xe7\x99\xbd,
wuse\n\xe5\x91\xb5\xe5\x91\xb5\n\xe6\x97\xa5\xe5\xa4\xa9'

rb的作用: 在读取非文本文件的时候. 比如读取MP3. 图像. 视频等信息的时候就需要用到rb. 因为这种数据是没办法直接显示出来的. 在后面我们文件上传下载的时候还会用到. 还有.我们看的直播. 实际上都是这种数据.

绝对路径和相对路径:
1.绝对路径:从磁盘根目录开始一直到文件名.

2.相对路径:同一个文件夹下的文件. 相对于当前这个程序所在的文件夹而言. 如果在同一个文件夹中. 则相对路径就是这个文件名. 如果在上一层文件夹. 则要 …/

我们更推荐大家使用相对路径. 因为在我们把程序拷贝给别人使用的时候. 直接把项目拷贝走就能运行. 但是如果用绝对路径. 那还需要拷贝外部的文件

只写(w , wb)

写的时候注意. 如果没有文件. 则会创建文件, 如果文件存在. 则将原件中原来的内容删除, 再
写入新内容

f = open("⼩娃娃", mode="w", encoding="utf-8")
f.write("⾦⽑狮王")
f.flush() # 刷新. 养成好习惯
f.close()

尝试读一读

f = open("⼩娃娃", mode="w", encoding="utf-8")
f.write("⾦⽑狮王")
f.read() # not readable 模式是w. 不可以执⾏读操作
f.flush()
f.close()

wb模式下. 可以不指定打开文件的编码. 但是在写文件的时候必须将字符串转化成utf-8的bytes数据

f = open("⼩娃娃", mode="wb")
f.write("⾦⽑狮王".encode("utf-8"))
f.flush()
f.close()

追加(a , ab)

在追加模式下. 我们写入的内容会追加在⽂件的结尾.

f = open("⼩娃娃", mode="a", encoding="utf-8")
f.write("麻花藤的最爱")
f.flush()
f.close()

读写(r+)

对于读写模式. 必须是先读. 因为默认光标是在开头的. 准备读取的. 当读完了之后再进行写入. 我们以后使用频率最高的模式就是r+
正确操作:

f = open("⼩娃娃", mode="r+", encoding="utf-8")
content = f.read()
f.write("麻花藤的最爱")
print(content)
f.flush()
f.close()
# 结果:
# 正常的读取之后, 写在结尾

错误操作:

f = open("⼩娃娃", mode="r+", encoding="utf-8")
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()
# 结果: 将开头的内容改写成了"哈哈", 然后读取的内容是后⾯的内容.
# 所以记住: r+模式下. 必须是先读取. 然后再写入

写读(w+)

先将所有的内容清空. 然后写入. 最后读取. 但是读取的内容是空的, 不常用

f = open("⼩娃娃", mode="w+", encoding="utf-8")
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()

w+ 模式下, 一开始读取不到数据. 然后写的时候再将原来的内容清空. 所以, 很少用.

追加写读(a+)

a+模式下, 不论先读还是后读. 都是读取不到数据的.

# a+ 可读可写
fp = open("ceshi5.txt",mode="a+",encoding="utf-8")
fp.write("123")

fp.seek(0)
res = fp.read()
print(res)

# a模式在写入内容时,会强制把光标移动到最后
fp.seek(1) # 虽然移到了索引为1的位置,但是在a+模式下,会强制把光标移到最后
fp.write("abc")

fp.close()

r+和a+的区别:a+是追加写,而r+只会在光标位置后写,不会像a+一样强制将光标拽到最后

with语法的使用

# with语法的使用 (close操作with语法可以自动实现)
with open("集合.png",mode="rb") as fp:
    res = fp.read()

# 赋予绝对路径
with open(r"E:\python31\day8\集合4.png",mode="wb") as fp:
    fp.write(res)

# 继续优化 合并with
with open("集合.png",mode="rb") as fp1 ,  open(r"E:\python31\day8\集合5.png",mode="wb") as fp2:
    res = fp1.read()
    fp2.write(res)

close:文件关闭的意义

# close 文件关闭的意义
"""
刷新缓冲区 flush
    # 当文件关闭的时候自动刷新缓冲区
    # 当整个程序运行结束的时候自动刷新缓冲区
    # 当缓冲区写满了  会自动刷新缓冲区
    # 手动刷新缓冲区
"""
fp = open("ceshi6.txt",mode="r+",encoding="utf-8")
fp.write("zzz")
# 手动把缓冲区里面的内容写入文件当中
fp.flush()

# 制造一个死循环,让其无法执行close函数
while True:
    pass

fp.close()

文件的相关函数

seek() 移动光标

seek(n) 光标移动到n位置, 注意, 移动的单位是byte. 所以如果是UTF-8的中文部分要是3的倍数.
通常我们使⽤seek都是移动到开头或者结尾.
移动到开头: seek(0)
移动到结尾: seek(0,2) seek的第二个参数表⽰的是从哪个位置进行偏移, 默认是0, 表示开头, 1表示当前位置, 2表示结尾

f = open("⼩娃娃", mode="r+", encoding="utf-8")
f.seek(0) # 光标移动到开头
content = f.read() # 读取内容, 此时光标移动到结尾
print(content)
f.seek(0) # 再次将光标移动到开头
f.seek(0, 2) # 将光标移动到结尾
content2 = f.read() # 读取内容. 什么都没有
print(content2)
f.seek(0) # 移动到开头
f.write("张国荣") # 写⼊信息. 此时光标在9 中⽂3 * 3个 = 9
f.flush()
f.close()

tell() 获取光标的当前位置

tell() 使用tell()可以帮我们获取到当前光标在什么位置

f = open("⼩娃娃", mode="r+", encoding="utf-8")
f.seek(0) # 光标移动到开头
content = f.read() # 读取内容, 此时光标移动到结尾
print(content)
f.seek(0) # 再次将光标移动到开头
f.seek(0, 2) # 将光标移动到结尾
content2 = f.read() # 读取内容. 什么都没有
print(content2)
f.seek(0) # 移动到开头
f.write("张国荣") # 写入信息. 此时光标在9 中文3 * 3个 = 9
print(f.tell()) # 光标位置9
f.flush()
f.close()

truncate() 截断⽂件

f = open("⼩娃娃", mode="w", encoding="utf-8")
f.write("哈哈") # 写⼊两个字符
f.seek(3) # 光标移动到3, 也就是两个字中间
f.truncate() # 删掉光标后⾯的所有内容
f.close()
f = open("⼩娃娃", mode="r+", encoding="utf-8")
content = f.read(3) # 读取12个字符
f.seek(4)
print(f.tell())
f.truncate() # 后⾯的所有内容全部都删掉
# print(content)
f.flush()
f.close()

深坑请注意: 在r+模式下. 如果读取了内容. 不论读取内容多少. 光标显示的是多少. 再写入
或者操作文件的时候都是在结尾进行的操作.
所以如果想做截断操作. 记住了. 要先挪动光标. 挪动到你想要截断的位置. 然后再进⾏截断
关于truncate(n), 如果给出了n. 则从开头开头进行截断, 如果不给n, 则从当前位置截断. 后⾯
的内容将会被删除

readable 判断文件对象是否可读

fp = open("ceshi6.txt",mode="a+",encoding="utf-8")
#readable()  功能: 判断文件对象是否可读
res = fp.readable()
print(res)

writable 判断文件对象是否可写

#writable()  功能: 判断文件对象是否可写
res = fp.writable()
print(res)

readline 读取一行文件内容

"""
原文件内容:
床前明月光
疑是地上霜
举头望明月
低头思故乡
"""

"""
参数 > 当前行字符总个数 => 以当前行读取
参数 < 当前行字符总个数 => 以参数的大小来读取字符的个数
默认readline 读取一行
"""

with open("ceshi7.txt", mode="r+", encoding="utf-8") as fp:
    res = fp.readline(3000)
    print(res)
    # 文件对象fp也是一个可迭代对象
    '''在遍历文件对象的时候,默认一次拿一行'''
    for i in fp:
        print(i)

用readline读取文件的所有内容

# readline读取所有内容
with open("ceshi7.txt",mode="r+",encoding="utf-8") as fp:    

    # 先读取一行
    res = fp.readline()
    # 判断是不是空
    while res:
        print(res)
        res = fp.readline()

readlines() 将文件中的内容按照换行读取到列表当中

#readlines()    功能:将文件中的内容按照换行读取到列表当中
lst_new = []
with open("ceshi7.txt",mode="r+",encoding="utf-8") as fp:    
    lst = fp.readlines()
    print(lst) # ['\t窗前明月光\n', '疑是鞋两双\t\t\n', '\t\t举头王明月\n', '\t低头看裤裆']
    for i in lst:        
        lst_new.append(i.strip())

print(lst_new)     # ['窗前明月光', '疑是鞋两双', '举头王明月', '低头看裤裆']

writelines() 将内容是字符串的可迭代性数据写入文件中

# writelines()   功能:将内容是字符串的可迭代性数据写入文件中 参数:内容为字符串类型的可迭代数据

"""可迭代型数据(容器类型数据,range对象,迭代器)"""
lst = ["春眠不觉晓\n","处处蚊子咬\n","夜来大狗熊\n","一个也跑不了\n"]
lst = [1,2,3,4]  # error 列表中的元素必须是字符串类型,而非数字类型
with open("ceshi8.txt",mode="w",encoding="utf-8") as fp:
    fp.writelines(lst)

truncate() 把要截取的字符串提取出来,然后清空内容将提取的字符串重新写入文件中 (字节)

#truncate()     功能: 把要截取的字符串提取出来,然后清空内容将提取的字符串重新写入文件中 (字节)
with open("ceshi7.txt",mode="r+",encoding="utf-8") as fp:
    fp.truncate(9) # 9代表9个字节,而不是9个字符
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值