一、引言:为什么需要文件操作?
在编程中,文件操作是程序与外部世界交换数据的重要桥梁。通过文件操作,我们可以:
- ✅ 保存数据:将程序运行中的数据持久化存储,避免重启后丢失。
- ✅ 读取数据:从外部文件加载配置、日志、用户数据等进行处理。
- ✅ 共享数据:与其他程序或系统通过文件格式(如 CSV、JSON、TXT)交换信息。
- ✅ 修改数据:对文件内容进行增删改查,实现数据管理功能。
Python 提供了简单而强大的内置函数和方法来进行文件操作,支持文本文件和二进制文件的处理,是日常开发中不可或缺的技能。
二、打开文件
使用 open()
函数打开文件,返回一个文件对象,用于后续的读写操作。
基本语法:
open(file, mode='r', encoding=None)
file
:文件路径(字符串)mode
:打开模式(见下表)encoding
:编码方式(如'utf-8'
,处理中文推荐指定)
1. 常见模式
模式 |
描述 |
|
只读(默认),文件必须存在 |
|
写入,文件存在则覆盖,不存在则创建 |
|
追加,在文件末尾添加内容,不存在则创建 |
|
独占创建,文件已存在则操作失败(避免覆盖) |
|
二进制(可与其他模式结合,如 |
|
文本模式(默认,可省略) |
✅ 推荐:使用 with
语句(上下文管理器)
with open("example.txt", "r", encoding="utf-8") as file:
# 在此范围内可以安全地操作文件
content = file.read()
print(content)
# 文件会在此处自动关闭,即使发生异常也安全!
✅ 优势:
- 自动管理资源,无需手动调用
file.close()
- 即使发生异常,也能确保文件被正确关闭
- 代码更简洁、安全
三、读取文件
1. 读取整个文件内容(read()
)
with open("example.txt", "r", encoding="utf-8") as file:
content = file.read()
print(content)
✅ 适合小文件。大文件可能导致内存占用过高。
2. 按行读取
2.1 使用 readline()
(逐行读取)
with open("example.txt", "r", encoding="utf-8") as file:
while True:
line = file.readline()
if not line: # 读到文件末尾返回空字符串
break
print(line.strip()) # strip() 移除换行符和空白
2.2 使用 readlines()
(一次性读取所有行)
with open("example.txt", "r", encoding="utf-8") as file:
lines = file.readlines() # 返回列表,每个元素是一行
for line in lines:
print(line.strip())
⚠️ 适合中等大小文件,大文件慎用。
2.3 直接遍历文件对象(推荐)
with open("example.txt", "r", encoding="utf-8") as file:
for line in file:
print(line.strip())
✅ 最简洁、高效的方式,逐行读取,内存友好。
四、写入文件
1. 写入单行(write()
)
with open("example.txt", "w", encoding="utf-8") as file:
file.write("Hello, World!\n") # \n 表示换行
⚠️ 使用 'w'
模式会覆盖原文件内容!
2. 写入多行(writelines()
)
lines = ["第一行\n", "第二行\n", "第三行\n"]
with open("example.txt", "w", encoding="utf-8") as file:
file.writelines(lines)
⚠️ writelines()
不会自动添加换行符,需在每行末尾手动添加 \n
。
五、追加内容到文件
with open("example.txt", "a", encoding="utf-8") as file:
file.write("这是追加的内容。\n")
✅ 使用 'a'
模式,新内容会添加到文件末尾,不会覆盖原有内容。
六、二进制文件操作
对于图片、视频、音频等非文本文件,必须使用二进制模式。
1. 写入二进制文件
data = b"Binary data here" # 字节串
with open("example.bin", "wb") as file: # 'wb' = write binary
file.write(data)
2. 读取二进制文件
with open("example.bin", "rb") as file: # 'rb' = read binary
binary_data = file.read()
print(binary_data) # 输出:b'Binary data here'
✅ 适用于复制文件、处理图像、网络传输等场景。
七、文件指针与定位
文件对象维护一个指针,指示当前读写位置。
1. 获取当前指针位置(tell()
)
with open("example.txt", "r", encoding="utf-8") as file:
print(f"初始位置:{file.tell()}") # 0
file.read(5)
print(f"读取5字节后位置:{file.tell()}") # 5
2. 移动指针位置(seek()
)
with open("example.txt", "r", encoding="utf-8") as file:
file.seek(5) # 将指针移动到第6个字节处(从0开始)
content = file.read() # 从位置5开始读取
print(content)
✅ seek(offset, whence)
:
offset
:偏移量whence
:参考位置(0=文件开头,1=当前位置,2=文件末尾)
八、其他常用操作(os
模块)
import os
1. 检查文件是否存在
if os.path.exists("example.txt"):
print("文件存在")
else:
print("文件不存在")
2. 获取文件大小
size = os.path.getsize("example.txt")
print(f"文件大小:{size} 字节")
3. 删除文件
os.remove("example.txt") # 谨慎使用!
4. 重命名文件
os.rename("old_name.txt", "new_name.txt")
5. 创建/删除目录
os.makedirs("new_folder", exist_ok=True) # 创建目录
os.rmdir("new_folder") # 删除空目录
九、综合示例:简单的日志记录器
import datetime
def log(message, filename="log.txt"):
"""
将带时间戳的日志消息追加到文件
"""
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}\n"
with open(filename, "a", encoding="utf-8") as log_file:
log_file.write(log_entry)
# 使用示例
log("程序启动")
log("用户登录成功")
log("执行数据处理任务")
✅ 日志文件 log.txt
内容示例:
[2025-08-13 19:00:00] 程序启动
[2025-08-13 19:00:05] 用户登录成功
[2025-08-13 19:00:10] 执行数据处理任务
十、总结:文件操作的核心要点
关键点 |
说明 |
打开文件 |
使用 |
读取文件 |
|
写入文件 |
|
追加内容 |
使用 |
二进制操作 |
使用 |
文件指针 |
|
文件状态 |
使用 |
编码处理 |
文本文件建议显式指定 |
十一、最佳实践与建议
建议 |
说明 |
✅ 始终使用 |
确保文件资源安全释放 |
✅ 显式指定编码 |
避免中文乱码问题,推荐 |
✅ 处理异常 |
使用 |
✅ 选择合适模式 |
写入用 |
✅ 大文件逐行处理 |
避免一次性读入内存导致崩溃 |
✅ 路径使用 |
提高跨平台兼容性 |
十二、动手练习
1. 统计文本文件中的单词数量
def count_words(filename):
try:
with open(filename, "r", encoding="utf-8") as file:
content = file.read()
words = content.split() # 按空白字符分割
return len(words)
except FileNotFoundError:
print(f"❌ 文件 '{filename}' 未找到")
return None
except Exception as e:
print(f"❌ 读取文件时出错:{e}")
return None
# 测试
word_count = count_words("example.txt")
if word_count is not None:
print(f"✅ 文件中共有 {word_count} 个单词")
2. 返回文件中最长的一行
def get_longest_line(filename):
try:
longest_line = ""
with open(filename, "r", encoding="utf-8") as file:
for line in file:
if len(line) > len(longest_line):
longest_line = line
return longest_line.strip() # 去除换行符
except FileNotFoundError:
print(f"❌ 文件 '{filename}' 未找到")
return None
# 测试
longest = get_longest_line("example.txt")
if longest:
print(f"最长的一行是:{longest}")
3. 简单的配置文件读取器(.ini 格式)
假设配置文件 config.txt
内容如下:
host=localhost
port=8080
debug=True
def read_config(filename):
config = {}
try:
with open(filename, "r", encoding="utf-8") as file:
for line in file:
line = line.strip()
if line and not line.startswith('#'): # 忽略空行和注释
key, value = line.split('=', 1) # 分割一次
config[key.strip()] = value.strip()
return config
except FileNotFoundError:
print(f"❌ 配置文件 '{filename}' 未找到")
return {}
except Exception as e:
print(f"❌ 解析配置文件失败:{e}")
return {}
# 使用
config = read_config("config.txt")
print("配置项:", config)
# 输出:{'host': 'localhost', 'port': '8080', 'debug': 'True'}
🚀 学习建议
- 多实践:尝试读写不同类型的文件(日志、CSV、配置文件)。
- 理解模式差异:掌握
'r'
,'w'
,'a'
,'x'
的行为差异。 - 结合异常处理:确保文件操作健壮。
- 进阶学习:
-
pathlib
模块(现代路径操作)json
模块(结构化数据存储)csv
模块(表格数据处理)- 上下文管理器自定义