python基础08文件操作

一、文件操作核心概念

先明确几个概念

概念 含义
文件路径 文件在系统中的位置,绝对路径,相对路径
文件模式 打开文件的方式,读,写,追加等
文件对象 打开文件后返回的对象,用于后续读写操作,通过open()函数获取
编码格式 文本文件的字符编码,utf-8,gbk,决定能否正确读写中文等特殊字符

二、基础文件操作:open() 与文件对象

open()函数是文件操作的入口,用于打开文件并返回文件对象,然后使用对象.方法就能完成日常的操作

open()函数参数详解

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

核心参数 作用说明 常用取值
file 必选,文件路径,字符串 “data.txt”
mode 打开模式,决定读写权限和文件类型 r,w,a,r+,wb+
encoding 文本模式下的编码格式(二进制模式无需指定,使用b) utf-8(支持中文),gbk

文件模式总表

分类 完整模式 默认缩写(常用形式) 数据格式 读写权限 文件存在性处理 初始指针位置 ️ 易错点
只读 rt r(默认) 文本 只读 必须存在(否则报错) 开头(0) 不可写,文件不存在抛FileNotFoundError
只读 rb rb 二进制 只读 必须存在(否则报错) 开头(0) 非文本文件(图片/视频)必用,否则数据损坏
只写 wt w(默认) 文本 只写 不存在则创建,存在则清空 开头(0) 覆盖原有内容,谨慎使用(不可恢复)
只写 wb wb 二进制 只写 不存在则创建,存在则清空 开头(0) 需传入bytes类型,字符串需用encode()转换
追加 at a(默认) 文本 只写 不存在则创建,存在则保留 末尾 无论指针位置,写入始终在末尾
追加 ab ab 二进制 只写 不存在则创建,存在则保留 末尾 适合日志追加、分片文件拼接
读写(保留原内容) rt+ r+(默认) 文本 读写 必须存在(否则报错) 开头(0) 写入覆盖当前指针位置内容,需用seek()控制指针
读写(保留原内容) rb+ rb+ 二进制 读写 必须存在(否则报错) 开头(0) 精确修改二进制数据(如图片元数据),需seek()定位字节
读写(清空原内容) wt+ w+(默认) 文本 读写 不存在则创建,存在则清空 开头(0) 读前需seek(0)(写入后指针在末尾),清空不可逆
读写(清空原内容) wb+ wb+ 二进制 读写 不存在则创建,存在则清空 开头(0) 新建并编辑二进制文件(如协议数据包)
追加+读 at+ a+(默认) 文本 读写 不存在则创建,存在则保留 末尾 读前需seek(0)(默认在末尾,直接读返回空)
追加+读 ab+ ab+ 二进制 读写 不存在则创建,存在则保留 末尾 追加后验证文件完整性(如校验MD5)

核心规则(一句话看懂)

  • r只读,文件不存在报错,w写,文件不存在创建,覆盖写入,a是文件不存在创建,追加写入

  • 二进制模式(b),就是针对一些mp3,mp4,JPG,png这些文件需要加上b,否则报错

基础操作流程:打开—>操作—>关闭

推荐使用with 语句自动关闭文件,无需手动调用close()

文本文件读写

# 写入文件
with open("123.txt","w",encoding="utf-8") as f:
    f.write("hello world\n")
    f.write("这首中文内容\n")  # 这个有个误区,一次性写入2行数据,如果下次再使用了w模式的话,就会将这2行的内容覆盖,当前代码不会覆盖,是一次性写了2行内容

# 读取文件

with open("123.txt","r",encoding="utf-8") as f:
    content = f.read()
    print(f"文件内容:\n{content}")

# 输出为
# 文件内容:
#  Hello, Python!
#  这是中文内容

二进制文件操作(图片,视频)

二进制文件必须用b模式,且无需指定encoding(这个是文本才能使用的)

复制一个图片流程

  • 读取这个图片保存到一个变量中

  • 然后将这个变量写入到另外一个图片中

  • 完成图片复制


# 先读取,保存这个内容

with open("1.jpg","rb") as f:
    data = f.read()

# 将内容写入到另一个图片中

with open("2.jpg","wb") as f:
    f.write(data)

print("图片复制完成")

上面这个图片案例,视频可以,就是可以利用到爬虫上,读取内容即可

三、文件读取的5种方式

方法 功能说明 文件指针变化 适用场景
read() 无参:读取文件全部内容;有参 n:读取至多 n 字节(二进制模式常用,文本模式需谨慎) 无参:从当前位置直读到 EOF,指针停在文件末尾;有参 n:向前移动 n 字节/字符。可配合 seek() 从指定位置读取 小文件(一次性处理全文);二进制大文件分块处理(如网络传输、分片复制)
readline() 读取一行内容(含换行符 \n),支持指定字节限制 limit(Python 3.2+) 从当前位置读到行尾,指针移至下一行开头;若已到 EOF 则保持不动 按行处理文件(如日志解析、CSV逐行读取);超大行文件(指定 limit 控制内存)
readlines() 读取所有行,返回列表(每行作为元素,含换行符 \n 从当前位置连续读取直至 EOF,指针最终停在文件末尾 中等大小文件,需按行索引访问(如按行号提取内容)或批量处理所有行
迭代文件对象(for line in f 自动逐行读取,循环内每次返回一行(含换行符 \n),底层调用 readline() 每次迭代指针向后移动一行,循环结束后位于 EOF;循环前可用 seek(0) 重新从头遍历 大/超大文件(内存友好,无需一次性加载全部内容),仅需顺序处理行数据

readline() 默认带上一个换行符
readlines() 读取所有行,返回一个列表

5种读取方式的对比

with open("123.txt","w",encoding="utf-8") as f:
    f.write("这个是第一行内容\n")
    f.write("这个是第二行内容\n")
    f.write("这个是第三行内容\n")


# read 读取全部的内容

with open("123.txt","r",encoding="utf-8") as f:
    print(f"1. read()结果为\n{f.read()}")

# 输出为
1. read()结果为
这个是第一行内容
这个是第二行内容
这个是第三行内容

# readline 读取一行的内容

with open("123.txt","r",encoding="utf-8") as f:
    print("2. readline()结果为:")
    print(f.readline(),end="")
    print(f.readline(),end="")

# 输出为
2. readline()结果为:
这个是第一行内容
这个是第二行内容



# readlines方法
with open("123.txt","r",encoding="utf-8") as f:
    lines = f.readlines()
    print(f"3. readlines()结果为:{lines}")
    print(f"访问第二行,根据索引:{lines[1]}")

# 输出为
3. readlines()结果为:['这个是第一行内容\n', '这个是第二行内容\n', '这个是第三行内容\n']
访问第二行,根据索引:这个是第二行内容


# 迭代文件对象

with open("123.txt","r",encoding="utf-8") as f:
    print(f"5. 迭代文件对象:")
    for line in f:
        print(f"行的内容:{line}",end="")

# 这个也是默认带上一个换行符,因为文本内容自带一个换行符

# 输出为

5. 迭代文件对象:
行的内容:这个是第一行内容
行的内容:这个是第二行内容
行的内容:这个是第三行内容


四、文件写入的3种方式

写入操作需要注意模式选择,w是覆盖,a是追加,以及换行符的处理

方法 功能说明
write(str) 写入字符串,返回写入的字符数
writelines(seq) 写入字符串序列(列表/元组等),不自动添加换行符
print(..., file=f) 用 print 函数写入,可自动添加换行符(end 参数控制)
# write() 返回的是写入的字符数

with open("123.txt","w",encoding="utf-8") as f:
    content1 = f.write("这个是写入第一行的内容\n")
    content2 = f.write("这个是写入第二行的内容")
    print(f"写入的字符数:{content1},{content2}")

# 输出结果为

写入的字符数:12,11

# writelines()

with open("123.txt","a",encoding="utf-8") as f:
    lines = ["\n写入到第三行的内容","用writelines写入第四行"]
    f.writelines(lines)  # 不会自动添加换行,文件内容是连在一起的

# 文件内容为
这个是写入第一行的内容
这个是写入第二行的内容
写入到第三行的内容用writelines写入第四行

# print() 函数写入,自动换行

with open("123.txt","a",encoding="utf-8") as f:
    print("\n用print写入第五行:",file=f)
    print("用print写入第六行:",file=f,end='---')


# 文件内容为
这个是写入第一行的内容
这个是写入第二行的内容
写入到第三行的内容用writelines
用print写入第五行:
用print写入第六行:---

五、文件指针与随机访问

文件对象内部有一个指针,记录当前读写位置,通过移动指针,可以实现随机读写(修改文件中间内容)

方法/属性 功能说明
tell() 返回当前指针位置(字节数)
seek(offset, whence) 移动指针到指定位置:
offset 偏移量(正数向后,负数向前);<
whence 基准位置(0:文件开头,1:当前位置,2:文件末尾)

文件指针操作


with open("123.txt","w",encoding="utf-8") as f:
    f.write("0123456789")
    print(f"写入指针后的位置:{f.tell()}")

# 输出结果为
写入指针后的位置:10


# 移动指针到开头,读取三个字符
    f.seek(0,0)
    print(f"移动到开头后读取:{f.read(3)}") # 输出为 012
    print(f"当前的指针位置:{f.tell()}")  # 输出当前指针为3


总结

注意的点:

  • 写入数据后,立刻进行读取,会读取不到,因为写入后,文件指针在文件的末尾,获取不到数据

  • 需要写入和读取的文件指针

文章摘自:https://www.cnblogs.com/qylogs/p/20074642