Python文件读写方法详解
1. 引言
文件操作是编程中最常见的任务之一,Python提供了强大而灵活的文件处理能力。无论是读取配置文件、处理日志数据、保存用户输入,还是进行数据分析,都离不开文件操作。本教程将全面介绍Python文件读写的方法,包括打开文件、读取内容、写入数据、关闭文件等基本操作,以及文件指针管理、二进制模式处理、异常处理等高级技巧。通过详细的代码示例和逐步解释,帮助您掌握Python文件操作的核心知识。
2. 打开文件
在Python中,使用内置的open()函数打开文件。这是所有文件操作的第一步,也是最关键的一步,因为它决定了文件的访问方式和权限。
2.1. 基本语法
file_object = open(file_path, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
2.2. 参数详解
file_path:文件路径(必需参数)
可以是绝对路径(如'C:/data/file.txt')或相对路径(如'data/file.txt')
在Windows系统中,反斜杠\需要转义('C:\\data\\file.txt')或使用原始字符串(r'C:\data\file.txt')
mode:文件打开模式(可选,默认为'r')
'r':只读模式(默认)
'w':写入模式(会覆盖已有内容)
'a':追加模式(在文件末尾添加内容)
'x':独占创建模式(文件不存在时创建,存在则报错)
'b':二进制模式(与其他模式组合使用)
't':文本模式(默认)
'+':读写模式(与其他模式组合使用)
encoding:文件编码(可选,文本模式有效)
常见编码:'utf-8'(推荐)、'gbk'、'ascii'、'latin-1'
如果不指定,使用系统默认编码
errors:编码错误处理策略(可选)
'strict':默认,遇到编码错误抛出异常
'ignore':忽略编码错误
'replace':用替换字符替代无法解码的内容
'backslashreplace':用Python反斜杠转义序列替换
newline:换行符处理(可选)
None:所有平台的换行符都转换为\n
'':不转换换行符
'\n'、'\r'、'\r\n':指定换行符
2.3. 示例代码
# 以只读模式打开UTF-8编码的文本文件
file1 = open('example.txt', 'r', encoding='utf-8')
# 以写入模式打开二进制文件
file2 = open('data.bin', 'wb')
# 以追加读写模式打开文件,指定编码错误处理
file3 = open('log.txt', 'a+', encoding='gbk', errors='replace')
2.4. 注意事项
打开文件后必须关闭文件,否则可能导致资源泄露
使用with语句可以自动管理文件关闭(推荐)
打开不存在的文件进行读操作会引发FileNotFoundError
打开已有文件进行写操作会覆盖原内容(使用'w'模式时)
3. 读取文件内容
打开文件后,可以使用多种方法读取文件内容,根据需求选择合适的方法。
3.1. read()方法
读取文件全部内容到字符串中。
file = open('example.txt', 'r', encoding='utf-8')
content = file.read() # 读取全部内容
file.close()
print(content)
参数说明:
size:可选参数,指定读取的字节数(文本模式)或字符数
如果省略size或指定为负数,读取整个文件
file = open('example.txt', 'r', encoding='utf-8')
first_10_chars = file.read(10) # 读取前10个字符
file.close()
print(first_10_chars)
3.2. readline()方法
读取文件中的一行内容。
file = open('example.txt', 'r', encoding='utf-8')
line1 = file.readline() # 读取第一行
line2 = file.readline() # 读取第二行
file.close()
print("第一行:", line1)
print("第二行:", line2)
特点:
保留行尾的换行符(\n)
文件末尾返回空字符串('')
3.3. readlines()方法
读取文件所有行到列表中。
file = open('example.txt', 'r', encoding='utf-8')
lines = file.readlines() # 读取所有行到列表
file.close()
for i, line in enumerate(lines, 1):
print(f"行 {i}: {line.strip()}") # 去除行尾空白
参数说明:
hint:可选参数,指定读取的行数(近似值)
如果文件很大,使用hint可以控制内存使用
3.4. 迭代文件对象
直接遍历文件对象逐行读取,推荐用于大文件处理。
file = open('example.txt', 'r', encoding='utf-8')
for line in file: # 逐行迭代
print(line.strip())
file.close()
3.5. 二进制文件读取
使用'rb'模式读取二进制文件。
file = open('data.bin', 'rb')
data = file.read() # 读取为字节串
file.close()
print("数据类型:", type(data))
print("数据内容:", data)
3.6. 完整示例:逐行读取并处理
# 打开文件
with open('example.txt', 'r', encoding='utf-8') as file:
line_number = 0
for line in file:
line_number += 1
# 去除行首尾空白
stripped_line = line.strip()
# 跳过空行
if not stripped_line:
continue
# 处理行内容
if 'error' in stripped_line.lower():
print(f"错误行 (行 {line_number}): {stripped_line}")
else:
print(f"正常行 (行 {line_number}): {stripped_line}")
4. 写入文件内容
Python提供了多种方法向文件写入内容,包括写入字符串、写入列表等。
4.1. write()方法
向文件写入字符串内容。
file = open('output.txt', 'w', encoding='utf-8')
file.write("第一行内容\n") # 写入字符串
file.write("第二行内容\n")
file.close()
注意:
write()方法不会自动添加换行符,需要手动添加\n
写入二进制数据需要使用'wb'模式
4.2. writelines()方法
向文件写入字符串列表。
lines = ["第一行\n", "第二行\n", "第三行\n"]
file = open('output.txt', 'w', encoding='utf-8')
file.writelines(lines) # 写入多行
file.close()
注意:
列表中的每个元素必须包含换行符(如果需要换行)
不会自动添加换行符
4.3. 二进制文件写入
data = b'\x48\x65\x6c\x6c\x6f' # 字节串(Hello的ASCII编码)
file = open('binary.bin', 'wb')
file.write(data)
file.close()
4.4. 追加内容
使用'a'模式在文件末尾追加内容。
file = open('output.txt', 'a', encoding='utf-8')
file.write("这是追加的内容\n")
file.close()
4.5. 完整示例:写入多行数据
# 准备数据
users = [
{"name": "Alice", "age": 30, "email": "alice@example.com"},
{"name": "Bob", "age": 25, "email": "bob@example.com"},
{"name": "Charlie", "age": 35, "email": "charlie@example.com"}
]
# 写入文件
with open('users.txt', 'w', encoding='utf-8') as file:
file.write("Name\tAge\tEmail\n") # 写入标题行
for user in users:
# 格式化数据并写入
line = f"{user['name']}\t{user['age']}\t{user['email']}\n"
file.write(line)
5. 文件指针操作
文件指针表示当前读写的位置,Python提供了操作文件指针的方法。
5.1. tell()方法
获取当前文件指针的位置(字节偏移量)。
file = open('example.txt', 'r', encoding='utf-8')
print("当前位置:", file.tell()) # 初始位置为0
file.read(5) # 读取5个字符
print("读取5个字符后位置:", file.tell())
file.close()
5.2. seek()方法
移动文件指针到指定位置。
file = open('example.txt', 'r', encoding='utf-8')
file.read(5) # 读取前5个字符
file.seek(0) # 移动回文件开头
content = file.read() # 重新读取全部内容
file.close()
print(content)
参数说明:
offset:偏移量(字节数)
whence:参考位置(可选,默认为0)
0:文件开头(默认)
1:当前位置
2:文件末尾
示例:
file = open('example.txt', 'r', encoding='utf-8')
# 移动到文件末尾前10个字节
file.seek(-10, 2)
last_10_bytes = file.read()
print("最后10个字节:", last_10_bytes)
file.close()
5.3. 注意事项
文本模式下,seek()只能移动到read()或tell()返回的位置
二进制模式下,可以自由移动到任何位置
追加模式('a')下,文件指针始终在文件末尾,seek()不影响写入位置
5.4. 完整示例:随机访问文件
with open('example.txt', 'r+', encoding='utf-8') as file:
# 读取前10个字符
first_part = file.read(10)
print("前10个字符:", first_part)
# 获取当前位置
current_pos = file.tell()
print("当前位置:", current_pos)
# 移动到文件开头
file.seek(0)
# 读取第一行
first_line = file.readline()
print("第一行:", first_line.strip())
# 移动回之前的位置
file.seek(current_pos)
# 继续读取
rest_content = file.read()
print("剩余内容:", rest_content[:50] + "...")
6. 关闭文件
文件操作完成后,必须关闭文件以释放系统资源。
6.1. close()方法
显式关闭文件。
file = open('example.txt', 'r', encoding='utf-8')
content = file.read()
file.close() # 关闭文件
6.2. 使用with语句(推荐)
自动管理文件的打开和关闭,即使发生异常也能正确关闭。
with open('example.txt', 'r', encoding='utf-8') as file:
content = file.read()
# 文件在这里自动关闭
print(content)
6.3. 为什么必须关闭文件
释放系统资源(文件描述符)
确保所有缓冲数据写入磁盘
避免其他进程无法访问该文件
防止数据损坏或丢失
6.4. 检查文件是否关闭
file = open('example.txt', 'r', encoding='utf-8')
print("文件是否关闭:", file.closed) # False
file.close()
print("文件是否关闭:", file.closed) # True
7. 文件操作模式详解
Python提供了多种文件操作模式,不同模式组合可以实现不同的访问需求。
7.1. 文本模式与二进制模式
文本模式(默认)
't':文本模式(默认)
自动编码/解码(如UTF-8)
自动转换换行符(\n、\r\n等)
二进制模式
'b':二进制模式
不进行编码/解码
不转换换行符
适用于非文本文件(图片、音频、视频等)
7.2. 基本访问模式
| 模式 | 描述 | 文件存在时 | 文件不存在时 | 指针位置 |
|------|------|-----------|------------|----------|
| 'r' | 只读 | 成功打开 | 报错 | 文件开头 |
| 'w' | 只写 | 截断文件(清空) | 创建新文件 | 文件开头 |
| 'a' | 只追加 | 在末尾追加 | 创建新文件 | 文件末尾 |
| 'x' | 独占创建 | 报错 | 创建新文件 | 文件开头 |
7.3. 组合模式
读写模式
'r+':读写(文件必须存在)
'w+':读写(文件存在则清空)
'a+':读写(文件不存在则创建,追加写入)
二进制组合
'rb':二进制只读
'wb':二进制只写
'ab':二进制追加
'rb+':二进制读写
'wb+':二进制读写(清空)
'ab+':二进制读写(追加)
7.4. 模式示例
# 只读模式
with open('data.txt', 'r') as f:
data = f.read()
# 只写模式(覆盖)
with open('output.txt', 'w') as f:
f.write("新内容")
# 追加模式
with open('log.txt', 'a') as f:
f.write("新日志条目\n")
# 读写模式
with open('data.txt', 'r+') as f:
content = f.read()
f.seek(0)
f.write("修改后的内容")
# 二进制读写
with open('image.png', 'rb') as f:
image_data = f.read()
# 二进制追加
with open('data.bin', 'ab') as f:
f.write(b'\x00\x01\x02')
7.5. 模式选择指南
只需要读取已有文件:'r'或'rb'
需要创建新文件或覆盖已有文件:'w'或'wb'
需要在文件末尾添加内容:'a'或'ab'
需要同时读取和写入:'r+'、'w+'或'a+'
处理文本文件:使用文本模式(默认或显式指定't')
处理非文本文件:必须使用二进制模式('b')
8. 二进制文件处理
二进制文件处理是文件操作中的重要部分,适用于处理图像、音频、视频、可执行文件等非文本数据。
8.1. 读取二进制文件
# 读取图片文件
with open('image.jpg', 'rb') as img_file:
image_data = img_file.read()
print("文件大小:", len(image_data), "字节")
# 显示前20个字节的十六进制表示
print("前20个字节:", image_data[:20].hex())
8.2. 写入二进制文件
# 创建简单的二进制数据
data = bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]) # PNG文件头
# 写入二进制文件
with open('test.png', 'wb') as f:
f.write(data)
print("二进制数据已写入")
8.3. 二进制文件修改
# 修改二进制文件的特定字节
with open('data.bin', 'r+b') as f:
# 读取前10个字节
first_bytes = f.read(10)
print("原始前10字节:", first_bytes)
# 修改第5个字节(索引4)
f.seek(4)
f.write(bytes([0xFF])) # 写入新字节
# 读取修改后的内容
f.seek(0)
modified_bytes = f.read(10)
print("修改后前10字节:", modified_bytes)
8.4. 结构化二进制数据处理
使用struct模块处理结构化二进制数据:
import struct
# 创建二进制数据(整数、浮点数、字符串)
packer = struct.Struct('i f 10s') # 整型、浮点型、10字节字符串
data = packer.pack(42, 3.14, b'Hello') # 打包数据
# 写入文件
with open('struct.bin', 'wb') as f:
f.write(data)
# 读取文件并解包
with open('struct.bin', 'rb') as f:
packed_data = f.read(packer.size)
unpacked_data = packer.unpack(packed_data)
print("解包后的数据:", unpacked_data)
# (42, 3.140000104904175, b'Hello')
8.5. 完整示例:复制二进制文件
def copy_binary_file(src_path, dst_path, chunk_size=8192):
"""
复制二进制文件(大文件分块处理)
:param src_path: 源文件路径
:param dst_path: 目标文件路径
:param chunk_size: 每次读取的块大小(字节)
"""
try:
with open(src_path, 'rb') as src_file:
with open(dst_path, 'wb') as dst_file:
while True:
chunk = src_file.read(chunk_size)
if not chunk:
break
dst_file.write(chunk)
print(f"文件 {src_path} 已成功复制到 {dst_path}")
except IOError as e:
print(f"复制文件时出错: {e}")
# 使用示例
copy_binary_file('source.jpg', 'destination.jpg')
9. 异常处理
文件操作中可能会遇到各种异常情况,良好的异常处理能增强程序的健壮性。
9.1. 常见文件异常
FileNotFoundError:文件不存在
尝试打开不存在的文件进行读取时抛出
PermissionError:权限错误
无足够权限访问文件或目录时抛出
IsADirectoryError:是目录而非文件
尝试打开目录而不是文件时抛出
FileExistsError:文件已存在
使用独占创建模式('x')打开已存在文件时抛出
NotADirectoryError:不是目录
尝试在非目录上执行目录操作时抛出
UnicodeDecodeError:Unicode解码错误
文本模式下编码不匹配时抛出
9.2. 基本异常处理
try:
file = open('nonexistent.txt', 'r', encoding='utf-8')
content = file.read()
file.close()
except FileNotFoundError:
print("错误:文件不存在!")
except PermissionError:
print("错误:没有权限访问文件!")
except Exception as e:
print(f"发生未知错误: {e}")
else:
print("文件读取成功")
print(content)
9.3. 使用with语句的异常处理
try:
with open('example.txt', 'r', encoding='utf-8') as file:
content = file.read()
except UnicodeDecodeError:
print("错误:文件编码不正确,请尝试其他编码")
except IOError as e:
print(f"文件I/O错误: {e}")
else:
print(content)
9.4. 检查文件是否存在
在打开文件前检查文件是否存在:
import os
file_path = 'example.txt'
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
else:
print(f"文件 {file_path} 不存在")
9.5. 创建目录(如果不存在)
import os
dir_path = 'data/output'
file_path = os.path.join(dir_path, 'result.txt')
try:
# 创建目录(如果不存在)
os.makedirs(dir_path, exist_ok=True)
# 写入文件
with open(file_path, 'w', encoding='utf-8') as file:
file.write("数据处理结果")
print(f"结果已保存到 {file_path}")
except Exception as e:
print(f"操作失败: {e}")
9.6. 完整异常处理示例
import os
def safe_read_file(file_path, encoding='utf-8'):
"""
安全读取文件(包含完整异常处理)
:param file_path: 文件路径
:param encoding: 文件编码
:return: 文件内容(字符串)
"""
try:
# 检查文件是否存在
if not os.path.exists(file_path):
raise FileNotFoundError(f"文件 {file_path} 不存在")
# 检查是否是文件而非目录
if not os.path.isfile(file_path):
raise IsADirectoryError(f"路径 {file_path} 是目录而非文件")
# 检查读取权限
if not os.access(file_path, os.R_OK):
raise PermissionError(f"没有权限读取文件 {file_path}")
# 尝试打开并读取文件
with open(file_path, 'r', encoding=encoding) as file:
content = file.read()
return content
except FileNotFoundError as e:
print(f"错误: {e}")
except IsADirectoryError as e:
print(f"错误: {e}")
except PermissionError as e:
print(f"错误: {e}")
except UnicodeDecodeError:
print(f"错误: 文件 {file_path} 编码不是 {encoding}")
except IOError as e:
print(f"文件I/O错误: {e}")
except Exception as e:
print(f"发生未知错误: {e}")
return None # 发生错误时返回None
# 使用示例
content = safe_read_file('example.txt')
if content is not None:
print("文件内容:")
print(content)
10. 实际应用示例
10.1. 示例1:读取CSV文件并处理
# 读取CSV文件并计算平均值
def analyze_csv(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as file:
# 跳过标题行
next(file)
total = 0
count = 0
for line in file:
# 去除空白并分割
parts = line.strip().split(',')
if len(parts) >= 2:
try:
value = float(parts[1])
total += value
count += 1
except ValueError:
continue # 跳过无效数据
if count > 0:
average = total / count
print(f"平均值: {average:.2f} (基于 {count} 个数据点)")
else:
print("没有有效数据")
except FileNotFoundError:
print(f"错误: 文件 {file_path} 不存在")
except Exception as e:
print(f"处理文件时出错: {e}")
# 使用示例
analyze_csv('data.csv')
10.2. 示例2:日志文件分析
# 分析日志文件中的错误
def analyze_log(file_path):
error_count = 0
warning_count = 0
try:
with open(file_path, 'r', encoding='utf-8') as file:
for line_num, line in enumerate(file, 1):
line = line.strip()
if "ERROR" in line:
error_count += 1
print(f"行 {line_num}: {line}")
elif "WARNING" in line:
warning_count += 1
print(f"\n统计结果:")
print(f"错误数: {error_count}")
print(f"警告数: {warning_count}")
except FileNotFoundError:
print(f"错误: 日志文件 {file_path} 不存在")
except Exception as e:
print(f"分析日志时出错: {e}")
# 使用示例
analyze_log('application.log')
10.3. 示例3:批量处理文件
import os
# 批量处理目录中的所有文本文件
def batch_process_text_files(directory, search_word, replacement):
"""
批量替换目录中所有文本文件中的指定单词
:param directory: 目录路径
:param search_word: 要搜索的单词
:param replacement: 替换后的单词
"""
# 遍历目录
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.txt'):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 替换单词
new_content = content.replace(search_word, replacement)
# 写回文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f"已处理文件: {file_path}")
except Exception as e:
print(f"处理文件 {file_path} 时出错: {e}")
# 使用示例
batch_process_text_files('data', 'error', 'issue')
10.4. 示例4:文件合并与分割
# 合并多个文件为一个文件
def merge_files(output_path, input_paths):
"""
合并多个文件为一个文件
:param output_path: 输出文件路径
:param input_paths: 输入文件路径列表
"""
try:
with open(output_path, 'wb') as out_file:
for path in input_paths:
try:
with open(path, 'rb') as in_file:
out_file.write(in_file.read())
print(f"已合并: {path}")
except Exception as e:
print(f"读取文件 {path} 时出错: {e}")
print(f"所有文件已合并到 {output_path}")
except Exception as e:
print(f"合并文件时出错: {e}")
# 使用示例
merge_files('combined.bin', ['file1.bin', 'file2.bin', 'file3.bin'])
11. 总结
本教程详细介绍了Python文件读写的方法,涵盖了从基础到高级的各个方面。我们学习了如何使用open()函数打开文件,探索了各种文件操作模式,掌握了读取和写入文本及二进制文件的不同方法。通过文件指针操作,我们实现了随机访问文件内容。我们还强调了正确关闭文件的重要性,并推荐使用with语句自动管理资源。
异常处理部分帮助您构建更健壮的文件操作程序,能够优雅地处理各种错误情况。二进制文件处理和结构化数据操作(如使用struct模块)扩展了文件处理的能力,使其能够处理更复杂的数据类型。实际应用示例展示了如何将所学知识应用于解决实际问题,如日志分析、CSV处理、批量文件操作和文件合并等。
掌握Python文件读写技巧是编程的基本技能,也是数据处理、系统管理和软件开发的重要基础。通过本教程的学习,您应该能够自信地处理各种文件操作任务,并根据实际需求选择最合适的方法和模式。在实际开发中,请务必注意文件权限、编码问题和异常处理,以确保程序的稳定性和可靠性。






