万恶之源-文件操作
本节主要内容:
- 初识 文件操作
- 只读(r, rb)
- 只写(w, wb)
- 追加(a, ab)
- r+读写
- w+写读
- a+写读(追加写读)
- 其他操作 方法
- 文件的修改以及另 一种打开 文件句句柄的 方式
主要内容:
一. 初识 文件操作
使 用python来读写 文件是非常简单的操作. 我们使 用open()函数来打开 一个 文件, 获取到 文件句句柄. 然后通过 文件句句柄就可以进 行行各种各样的操作了了. 根据打开 方式的不同能够执 行行的操作也会有相应的差异.
打开 文件的 方式: r, w, a, r+, w+, a+, rb, wb, ab, r+b, w+b, a+b 默认使 用的是r(只读)模式
二. 只读操作(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. read() 将 文件中的内容全部读取出来. 弊端: 占内存. 如果 文件过 大.容易易导致内存崩溃
f = open("../def/哇擦.txt", mode="r", encoding="utf-8") content = f.read()
print(content)
结果:
友谊地久天 长,爱 一点,可惜我是 水瓶座 一 生中最爱
- 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)
结果:
友谊地
久天 长
- readline() 一次读取 一 行行数据, 注意: readline()结尾, 注意每次读取出来的数据都会有 一个\n 所以呢. 需要我们使 用strip() 方法来去掉\n或者空格
f = open("../def/哇擦.txt", mode="r", encoding="utf-8") content = f.readline()
content2 = f.readline() content3 = f.readline() content4 = f.readline() content5 = f.readline() content6 = f.readline() print(content) print(content2) print(content3) print(content4) print(content5) print(content6)
结果:
友谊地久天 长,
爱 一点,
可惜我是 水瓶座
一 生中最爱
- 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()
三. 写模式(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()
ab模式 自 己试 一试就好了了
五. 读写模式(r+, r+b)
对于读写模式. 必须是先读. 因为默认光标是在开头的. 准备读取的. 当读完了了之后再进 行行写入. 我们以后使 用频率最 高的模式就是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+, w+b)
先将所有的内容清空. 然后写入. 最后读取. 但是读取的内容是空的, 不常 用
f = open(" 小娃娃", mode="w+", encoding="utf-8") f.write("哈哈")
content = f.read() print(content) f.flush() f.close()
有 人会说. 先读不就好了了么? 错. w+ 模式下, 一开始读取不到数据. 然后写的时候再将原来
的内容清空. 所以, 很少 用.
七. 追加读(a+) a+模式下, 不论先读还是后读. 都是读取不到数据的.
f = open(" 小娃娃", mode="a+", encoding="utf-8") f.write(" 马化腾")
content = f.read() print(content)
f.flush()
f.close()
还有 一些其他的带b的操作. 就不多赘述了了. 就是把字符换成字节. 仅此 而已
八. 其他相关操作
- 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()
2. 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()
3. 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, 则从当前位置截断. 后 面的内容将会被删除
九. 修改 文件以及另 一种打开 文件的 方式
文件修改: 只能将 文件中的内容读取到内存中, 将信息修改完毕, 然后将源 文件删除, 将新 文件的名字改成老 文件的名字.
# 文件修改 import os
with open(" 小娃娃", mode="r", encoding="utf-8") as f1,\ open(" 小娃娃_new", mode="w", encoding="UTF-8") as f2:
content = f1.read()
new_content = content.replace("冰糖葫芦", " 大 白梨梨") f2.write(new_content)
os.remove(" 小娃娃") # 删除源 文件
os.rename(" 小娃娃_new", " 小娃娃") # 重命名新 文件
弊端: 一次将所有内容进 行行读取. 内存溢出. 解决 方案: 一 行行 一 行行的读取和操作
import os |
|
|
with open(" 小娃娃", |
mode="r", encoding="utf-8") as f1,\ |
|
open(" 小娃娃_new", mode="w", encoding="UTF-8") as f2: |
||
for line in f1: |
|
|
new_line = |
line.replace(" 大 白梨梨", "冰糖葫芦") |
|
f2.write(new_line) |
|
|
os.remove(" 小娃娃") |
# 删除源 文件 |
|
os.rename(" 小娃娃_new", " 小娃娃") |
# 重命名新 文件 |
|
|
|
|
# 路径有两种:
# 1. 相对路径, 相对于你当前程序所在的文件夹.(必须掌握)
# ../ 返回上一层目录
# 相对的是当前程序所在的文件夹
# 2. 绝对路径. 1.从磁盘根目录寻找. 2.互联网上的一个绝对路路径
# f = open("../wuse", mode="r", encoding="utf-8")
# s = f.read()
# f.close() # 关闭句柄
# print(s)
f = open("wudi", mode="r", encoding="utf-8")
for line in f: # 每次读取一行. 赋值给前面的line变量
print(line)
f.close()
f = open("wudi", mode="w", encoding="utf-8") # 写入之前会情掉原来的内容
f.write("杜十娘")
f.flush()
f.close()
f = open("小护士模特", mode="w", encoding="utf-8") # 写入之前会情掉原来的内容
f.write("杜十娘")
f.flush()
f.close()
f = open("小护士模特", mode="a", encoding="utf-8") # 在原来的基础上进行追加内容.
f.write("小龙女")
f.flush()
f.close()
f = open("小护士模特",mode="rb") # 读取的内容直接就是字节
bs = f.read()
print(bs.decode("utf-8")) # 需要解码
f.close()
f = open("小护士模特",mode="wb") # 读取的内容直接就是字节
f.write("你不好".encode("utf-8"))
f.close()
# w, r, a === wb, rb, ab b: 处理的是非文本
# f = open("老师点名", mode="r+", encoding="utf-8") # r+模式, 默认情况下光标在文件的开头, 必须先读, 后写
# f.read()
# f.write("周润发")
# f.flush()
# f.close()
# q = open('老师点名',mode='r+',encoding='utf-8')
# q.write('小伙子')#这种先写后读,第一行内容会被覆盖
# a = q.read()
# q.flush()
# q.close()
# print(a)
# f = open("精品", mode="r+", encoding="utf-8")
# s = f.read(3)
# # 不管你前面读了几个. 后面去写都是在末尾
# f.write("哈哈") # 1.在没有任何操作之前进行写. 在开头写 2. 如果读取了一些内容. 再写, 写入的是最后
#
# print(s)
# f = open("精品", mode="r+", encoding="utf-8")
# f.read(3)
# f.seek(3) # 移动到xx位置,移动3个字节
# f.write('牛批')
# # 移动到开头: f.seek(0) 开头
# # 移动到末尾: f.seek(0, 2) 末尾 第二个参数有三个值. 0: 再开头, 1: 在当前, 2: 末尾
#超人的都是精品.abcdefg潘长江是精品巴拉巴拉小魔仙哈哈
# f.seek(6) # 移动6个字节. 2个字
# s = f.read(3) # 读取3个字
# print(s)
# f.seek(0)
# ss = f.read(3)
# print(ss)
# s = f.read()
# f.seek(0)
# ss= f.read()
# print(s)
# print(ss)
f = open("亵渎", mode="w+", encoding="utf-8") # w 操作.会清空原来的内容. w+是不用的.
f.write("今天天气")
f.seek(0)
s = f.read()
print(s)
f.flush()
f.close()
import os标签:文件,utf,encoding,python,content,mode,print,操作,open From: https://www.cnblogs.com/hcx990214/p/16629023.html
with open('吃的',mode='r',encoding='utf-8')as f1,\
open('吃的副本',mode='w',encoding='utf-8')as f2:
s = f1.read()
w = s.replace('肉','仙')
f2.write(w)
os.remove('吃的')# 删除文件
os.rename('吃的副本','吃的')#吃的副本