一、文件操作的核心概念
- 文件路径 :文件在电脑中的位置(如
C:\Users\XXX\Desktop\test.txt(Windows)或/Users/XXX/Desktop/test.txt(Mac/Linux))- 绝对路径:从根目录开始的完整路径
- 相对路径:相对于当前程序所在文件夹的路径(如
./test.txt表示程序同文件夹下的 test.txt)
- 文件模式:打开文件的方式(读、写、追加、二进制等),后面会详细讲
- 文件句柄:打开文件后返回的 "操作对象",可以理解为 "文件的遥控器",所有操作都通过它完成
- 编码格式 :文件的字符编码(最常用的是
utf-8,避免中文乱码)
二、文件操作的基本流程
无论哪种文件操作,核心流程都是:
打开文件(open) → 操作文件(读/写/修改) → 关闭文件(close)
重点:打开的文件必须关闭,否则会占用电脑内存,甚至导致文件损坏!
三、基础操作:打开与关闭文件
3.1 用open()函数打开文件
open()是 Python 内置的打开文件的函数,语法:
python
文件句柄 = open(文件路径, 模式, encoding=编码格式)
| 参数 | 作用 |
|---|---|
| 文件路径 | 字符串类型,必填;可以是绝对路径或相对路径 |
| 模式 | 字符串类型,可选(默认是r);决定打开文件的方式 |
| encoding | 字符串类型,可选;指定文件编码(推荐utf-8,解决中文乱码) |
常用文件模式
| 模式 | 含义 | 注意事项 |
|---|---|---|
r |
只读模式(默认) | 文件必须存在,否则报错 |
w |
写入模式 | 文件不存在则创建,存在则清空原有内容 |
a |
追加模式 | 文件不存在则创建,新内容追加到文件末尾 |
r+ |
读写模式 | 文件必须存在,可读可写 |
w+ |
写读模式 | 清空原有内容,可写可读 |
a+ |
追加 + 读模式 | 新内容追加到末尾,可读可写 |
rb |
二进制只读模式(如图片、视频、exe 文件) | 不指定 encoding,按字节操作 |
wb |
二进制写入模式 | 同上 |
3.2 用close()关闭文件
打开文件后,必须用close()关闭,示例:
python
# 第一步:打开文件(桌面的test.txt,只读模式,utf-8编码)
# 注意:Windows路径中的\需要转义为\\,或用r前缀(原始字符串)
f = open(r"C:\Users\XXX\Desktop\test.txt", "r", encoding="utf-8")
# (这里可以加读/写操作)
# 第三步:关闭文件
f.close()
3.3 更安全的方式:with语句
手动close()容易忘记,Python 提供了with语句,自动关闭文件,即使代码出错也会关闭,语法:
python
with open(文件路径, 模式, encoding=编码格式) as 文件句柄:
# 缩进内:执行文件操作
# 缩进结束:自动关闭文件
python
# 用with打开文件,自动关闭
with open(r"C:\Users\XXX\Desktop\test.txt", "r", encoding="utf-8") as f:
# 这里写操作代码
content = f.read() # 读取文件内容
print(content)
# 缩进结束,文件已自动关闭,无需写f.close()
✅ 小白建议:所有文件操作优先用 with 语句,避免忘记关闭文件的坑!
四、文件读取操作
读取文件是获取文件内容的过程,有 4 种常用方法,覆盖所有场景:
4.1 读取全部内容:read()
语法:文件句柄.read(size)
size(可选):指定读取的字节数,不写则读取全部- 适合小文件(一次性读入内存)
python
# 读取整个文件内容
with open("test.txt", "r", encoding="utf-8") as f: # 相对路径(程序同文件夹)
all_content = f.read()
print("文件全部内容:")
print(all_content)
4.2 按行读取:readline()
语法:文件句柄.readline()
- 每次读取一行 内容(包括换行符
\n) - 适合大文件(逐行读,节省内存),可配合循环使用
python
# 逐行读取文件
with open("test.txt", "r", encoding="utf-8") as f:
# 读取第一行
line1 = f.readline()
print("第一行:", line1) # 输出带换行符,所以print后会多一空行
# 读取第二行
line2 = f.readline()
print("第二行:", line2.strip()) # strip()去掉换行符/空格
# 读取第三行
line3 = f.readline()
print("第三行:", line3.strip())
# 读取第四行(无内容,返回空字符串)
line4 = f.readline()
print("第四行:", repr(line4)) # repr显示空字符串
输出:
python
第一行: Hello Python!
第二行: 我是文件操作的测试内容
第三行: 第3行
第四行: ''
4.3 读取所有行到列表:readlines()
语法:文件句柄.readlines()
- 将文件的每一行作为列表的一个元素,返回列表
- 适合需要对每行内容做批量处理的场景
python
with open("test.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
print("所有行的列表:", lines)
# 遍历列表,处理每行
for i, line in enumerate(lines): # enumerate获取行号+内容
print(f"第{i+1}行:{line.strip()}")
输出:
python
所有行的列表: ['Hello Python!\n', '我是文件操作的测试内容\n', '第3行']
第1行: Hello Python!
第2行: 我是文件操作的测试内容
第3行: 第3行
4.4 直接遍历文件句柄(最推荐的逐行读取方式)
语法:for line in 文件句柄:
- 逐行读取,内存占用最少,适合超大文件(如 10G 的日志文件)
- 代码最简洁
python
# 遍历文件句柄,逐行读取(最优方式)
with open("test.txt", "r", encoding="utf-8") as f:
for line_num, line in enumerate(f, start=1): # start=1表示行号从1开始
print(f"第{line_num}行内容:{line.strip()}")
输出和上面一致,但内存效率更高!
读取的常见问题与解决
-
中文乱码 :打开文件时指定
encoding="utf-8" -
(如果还是乱码,试试
gbk,Windows 记事本默认编码是 gbk)python# 解决乱码:切换编码 with open("test.txt", "r", encoding="gbk") as f: print(f.read()) -
文件不存在报错 :
FileNotFoundError,检查路径是否正确,或先判断文件是否存在
五、文件写入操作
写入文件是将内容保存到文件的过程,核心模式:w(覆盖)、a(追加)。
5.1 覆盖写入:w模式
⚠️ 重点:w模式会清空文件原有内容,再写入新内容;如果文件不存在,会自动创建。
语法:文件句柄.write(内容)
- 内容必须是字符串类型(数字需要转成 str)
write()返回写入的字符数
示例 1:写入简单内容
python
# 覆盖写入(文件不存在则创建)
with open("write_test.txt", "w", encoding="utf-8") as f:
# 写入字符串
f.write("这是用w模式写入的内容\n")
f.write("第二行内容\n")
# 写入数字(需转字符串)
f.write(str(123456))
执行后,write_test.txt内容:
python
这是用w模式写入的内容
第二行内容
123456
示例 2:多次写入(覆盖原有内容)
python
# 第一次写入
with open("write_test.txt", "w", encoding="utf-8") as f:
f.write("第一次写入的内容")
# 第二次写入(覆盖第一次的内容)
with open("write_test.txt", "w", encoding="utf-8") as f:
f.write("第二次写入的内容(覆盖了之前的)")
最终文件内容:第二次写入的内容(覆盖了之前的)
5.2 追加写入:a模式
a模式不会清空原有内容,新内容追加到文件末尾;文件不存在则创建。
python
# 第一步:先写入初始内容
with open("append_test.txt", "w", encoding="utf-8") as f:
f.write("初始内容\n")
# 第二步:追加内容(用a模式)
with open("append_test.txt", "a", encoding="utf-8") as f:
f.write("追加的第一行\n")
f.write("追加的第二行\n")
# 查看最终内容
with open("append_test.txt", "r", encoding="utf-8") as f:
print(f.read())
输出:
初始内容
追加的第一行
追加的第二行
5.3 写入多行:writelines()
如果有一个字符串列表,想把每个元素作为一行写入,用writelines():
python
# 准备要写入的行列表
lines = [
"第一行\n", # 手动加换行符,否则会连在一起
"第二行\n",
"第三行"
]
with open("lines_test.txt", "w", encoding="utf-8") as f:
f.writelines(lines)
文件内容:
第一行
第二行
第三行
写入的注意事项
- 写入的内容必须是字符串 :数字、列表等需用
str()转换 - 换行需要手动加
\n:否则所有内容会写在一行 w模式慎用:确认不需要保留原有内容时再用
六、文件的高级操作
6.1 检查文件 / 文件夹是否存在(避免报错)
用os模块(Python 内置)检查路径是否存在,避免FileNotFoundError:
python
import os # 导入os模块
# 1. 检查文件是否存在
file_path = "test.txt"
if os.path.exists(file_path):
print(f"文件{file_path}存在")
else:
print(f"文件{file_path}不存在")
# 2. 检查是否是文件(避免路径是文件夹)
if os.path.isfile(file_path):
print(f"{file_path}是文件")
# 3. 检查是否是文件夹
folder_path = "./test_folder"
if os.path.isdir(folder_path):
print(f"{folder_path}是文件夹")
6.2 文件重命名与删除
用os模块实现文件重命名和删除:
python
import os
# 1. 重命名文件(旧路径,新路径)
os.rename("old_name.txt", "new_name.txt")
# 2. 删除文件(谨慎使用!删除后无法恢复)
if os.path.exists("delete_me.txt"): # 先检查是否存在
os.remove("delete_me.txt")
print("文件已删除")
else:
print("文件不存在")
6.3 文件夹操作
python
import os
# 1. 创建文件夹
folder_name = "new_folder"
if not os.path.exists(folder_name):
os.mkdir(folder_name) # 创建单层文件夹
# os.makedirs("a/b/c") # 创建多层文件夹(如a文件夹下的b,b下的c)
# 2. 删除文件夹(空文件夹)
if os.path.exists(folder_name):
os.rmdir(folder_name)
# 3. 删除非空文件夹(需用shutil模块)
import shutil
shutil.rmtree("non_empty_folder") # 谨慎使用!
6.4 二进制文件操作(图片 / 视频 / 音频)
操作图片、视频等二进制文件时,用rb/wb模式,不指定 encoding:
python
# 复制一张图片(二进制读取→二进制写入)
with open("original.jpg", "rb") as f_read: # 二进制只读
img_data = f_read.read() # 读取二进制数据
with open("copy.jpg", "wb") as f_write: # 二进制写入
f_write.write(img_data) # 写入二进制数据
print("图片复制完成")
6.5 文件指针操作(移动读取 / 写入位置)
文件打开后,有一个 "指针"(光标),默认在文件开头,读取 / 写入后指针会移动。用seek()手动移动指针:
python
with open("test.txt", "r", encoding="utf-8") as f:
# 读取前5个字符
print(f.read(5)) # 输出:Hello
# 指针现在在第5个字符位置
# 移动指针到文件开头(0表示开头,2表示末尾)
f.seek(0)
# 再次读取全部内容
print(f.read()) # 输出完整内容
七、实战案例
案例 1:统计文件的行数和字符数
python
# 统计test.txt的行数、字符数(排除空格/换行)
file_path = "test.txt"
line_count = 0 # 行数
char_count = 0 # 字符数
with open(file_path, "r", encoding="utf-8") as f:
for line in f:
line_count += 1 # 每行计数+1
# 去掉换行符、空格,统计有效字符
clean_line = line.strip().replace(" ", "")
char_count += len(clean_line)
print(f"文件总行数:{line_count}")
print(f"文件有效字符数:{char_count}")
案例 2:批量修改文件内容(替换指定字符串)
python
# 将test.txt中的"Python"替换为"Java",保存到新文件
with open("test.txt", "r", encoding="utf-8") as f_read:
with open("test_new.txt", "w", encoding="utf-8") as f_write:
for line in f_read:
# 替换字符串
new_line = line.replace("Python", "Java")
# 写入新文件
f_write.write(new_line)
print("替换完成,新文件已保存")
案例 3:读取大文件(避免内存溢出)
python
# 读取10G的超大日志文件,逐行处理(只打印包含"error"的行)
big_file_path = "big_log.txt"
error_count = 0
with open(big_file_path, "r", encoding="utf-8") as f:
for line in f: # 逐行读取,内存只存一行
if "error" in line.lower(): # 忽略大小写
print(f"错误行:{line.strip()}")
error_count += 1
print(f"总共找到{error_count}个错误行")
八、常见错误与解决方案
| 错误类型 | 原因 | 解决方案 |
|---|---|---|
FileNotFoundError |
文件路径错误 / 文件不存在 | 检查路径拼写;用os.path.exists()先判断 |
UnicodeDecodeError |
编码格式不匹配(如文件是 gbk,用 utf-8 读) | 切换 encoding(utf-8/gbk) |
PermissionError |
没有文件读写权限 / 文件被其他程序占用 | 关闭占用文件的程序;检查文件权限 |
IsADirectoryError |
路径指向文件夹,却当作文件操作 | 检查路径是否是文件(os.path.isfile()) |
总结
- 核心流程 :文件操作的基础是
打开→操作→关闭,优先用with语句自动关闭文件,避免内存泄漏; - 核心模式 :读取用
r,覆盖写入用w,追加写入用a,二进制文件用rb/wb; - 核心方法 :读取用
read()(小文件)/for line in f(大文件),写入用write(),批量写入用writelines(); - 避坑要点 :写入内容必须是字符串,中文乱码指定
encoding="utf-8",w模式会覆盖原有内容需慎用。
3.1 读取方法(文本文件)
| 方法 | 作用 | 适用场景 |
|---|---|---|
f.read() |
一次性读取文件全部内容 | 小体积文本文件 |
f.readline() |
逐行读取,单次仅读一行 | 逐行处理、大文件分步读取 |
f.readlines() |
读取所有行,返回字符串列表 | 需批量处理每行内容 |
for line in f: |
迭代逐行读取,内存占用极低 | 超大文本文件、日志文件 |
3.2 写入方法(文本文件)
| 方法 | 作用 | 注意事项 |
|---|---|---|
f.write(字符串) |
写入单行内容 | 需手动加换行符\n,仅支持字符串 |
f.writelines(列表) |
批量写入多行内容 | 列表元素需为字符串,换行需手动添加 |
3.3 文件/文件夹管理(os模块常用操作)
| 操作类型 | 核心语法 | 备注 |
|---|---|---|
| 判断路径是否存在 | os.path.exists(路径) |
判断文件/文件夹,返回布尔值 |
| 判断是否为文件 | os.path.isfile(路径) |
区分文件与文件夹 |
| 文件重命名 | os.rename(旧名, 新名) |
需保证原文件存在 |
| 删除文件 | os.remove(文件路径) |
删除后无法恢复,谨慎使用 |
| 创建文件夹 | os.mkdir(文件夹名) os.makedirs(路径) |
创建单层目录 可一次性创建多级目录,无需逐层级创建 |
| 删除空文件夹 | os.rmdir(文件夹名) |
仅支持删除空目录 |