Python TXT文件读写全攻略:高效处理文本数据的核心技巧与最佳实践256


在日常的编程任务中,文件操作是不可或缺的一环。无论是读取配置文件、日志文件,还是存储程序生成的数据,文本文件(尤其是TXT格式)都扮演着重要的角色。作为一门以简洁和强大著称的语言,Python为我们提供了极其方便且功能丰富的工具来处理TXT文件。本文将作为一份全面的指南,从基础概念到高级技巧,深入探讨如何使用Python高效、安全地打开、读取和写入TXT文件。

一、初识文件操作:open() 函数

Python 中进行文件操作的核心是内置的 `open()` 函数。它负责建立程序与文件之间的连接,并返回一个文件对象(也称为文件句柄),我们通过这个文件对象来执行后续的读写操作。

`open()` 函数的基本语法如下:
file_object = open(file_path, mode='r', encoding='utf-8', errors='strict')


`file_path`:必需参数,表示要打开的文件路径(可以是相对路径或绝对路径)。
`mode`:可选参数,用于指定文件打开的模式。默认为 `'r'`(读取模式)。
`encoding`:可选参数,指定文件的编码格式。对于文本文件,这是一个至关重要的参数,推荐始终明确指定为 `'utf-8'`,以避免乱码问题。
`errors`:可选参数,用于指定如何处理编码和解码错误。默认为 `'strict'`(遇到错误时抛出异常)。其他常用值包括 `'ignore'`(忽略错误)和 `'replace'`(用占位符替换错误字符)。

二、文件打开模式详解(mode)

`mode` 参数决定了我们对文件能进行何种操作。了解不同的模式对于正确处理文件至关重要:
`'r'` (read):只读模式。文件必须存在,否则会抛出 `FileNotFoundError`。这是默认模式。
`'w'` (write):只写模式。

如果文件存在,其内容将被截断(清空)并从头开始写入。
如果文件不存在,则会创建一个新文件。


`'a'` (append):追加模式。

如果文件存在,新的内容会被写入到文件末尾。
如果文件不存在,则会创建一个新文件。


`'x'` (exclusive creation):独占创建模式。

如果文件不存在,则创建并以只写模式打开。
如果文件已存在,则会抛出 `FileExistsError` 异常,阻止覆盖现有文件。这对于确保文件不会意外被覆盖非常有用。


`'r+'` (read and write):读写模式。文件必须存在,允许同时进行读写操作,写入从文件开头开始。
`'w+'` (write and read):写读模式。如果文件存在则清空,不存在则创建。允许同时进行读写操作。
`'a+'` (append and read):追加读模式。如果文件存在则在末尾追加,不存在则创建。允许同时进行读写操作。

此外,还可以通过在模式后添加 `'b'` 来指定二进制模式(例如 `'rb'`, `'wb'`, `'ab'`)。二进制模式适用于处理图片、视频等非文本文件,本文主要关注文本文件,因此将默认使用文本模式。

三、最佳实践:使用 `with` 语句管理文件

文件操作涉及系统资源,因此在完成操作后务必关闭文件,释放资源。忘记关闭文件可能导致数据丢失、资源泄漏或文件损坏。Python 的 `with` 语句(上下文管理器)是处理文件操作的最佳方式,它能确保文件在操作结束后(无论是正常结束还是发生异常)自动关闭。

不推荐的做法:
file = open('', 'r', encoding='utf-8')
try:
content = ()
print(content)
finally:
() # 必须手动关闭,容易遗漏

推荐的做法(使用 `with` 语句):
with open('', 'r', encoding='utf-8') as file:
content = ()
print(content)
# 文件在with块结束时自动关闭,无需手动调用 ()

使用 `with` 语句不仅代码更简洁,而且更健壮。强烈建议在所有文件操作中都采用这种方式。

四、读取TXT文件:多种方法

打开文件后,有多种方法可以读取其内容,选择哪种方法取决于文件的内容大小和你的具体需求。

1. read():读取整个文件


`read()` 方法会读取文件的全部内容,并将其作为一个字符串返回。如果文件非常大,这可能会占用大量内存。
with open('', 'r', encoding='utf-8') as f:
full_content = ()
print(full_content)

你也可以传入一个整数参数 `size` 给 `read(size)`,表示读取指定数量的字符。

2. readline():逐行读取


`readline()` 方法每次读取文件中的一行内容,包括行末的换行符 ``,并将其作为一个字符串返回。当读取到文件末尾时,它返回一个空字符串 `''`。
with open('', 'r', encoding='utf-8') as f:
line1 = ()
line2 = ()
print("第一行:", ()) # strip() 用于去除行末换行符
print("第二行:", ())

3. readlines():读取所有行到列表中


`readlines()` 方法会读取文件的所有行,并将它们存储在一个列表中,列表的每个元素都是文件中的一行(包含换行符)。同样,对于大文件,这也会占用大量内存。
with open('', 'r', encoding='utf-8') as f:
all_lines = ()
for line in all_lines:
print(())

4. 迭代文件对象:高效逐行读取(推荐)


Python 的文件对象是可迭代的(iterable),这意味着我们可以直接在 `for` 循环中迭代文件对象,每次迭代获取一行内容。这是处理大文件的最佳方式,因为它不会一次性将所有内容加载到内存中,而是按需读取。
with open('', 'r', encoding='utf-8') as f:
for line in f: # 逐行迭代,内存效率高
print(())

五、写入TXT文件:创建与修改

写入文件通常使用 `'w'`(写入)或 `'a'`(追加)模式。

1. write():写入字符串


`write()` 方法将一个字符串写入文件。需要注意的是,它不会自动添加换行符,如果你想每写入一个字符串就换行,需要手动添加 ``。
# 写入新文件或覆盖现有文件
with open('', 'w', encoding='utf-8') as f:
("这是第一行内容。")
("这是第二行内容。")
("这是没有换行的内容。")
# 验证内容
with open('', 'r', encoding='utf-8') as f:
print("--- 内容 ---")
print(())

2. writelines():写入字符串列表


`writelines()` 方法接受一个字符串列表作为参数,并将列表中的所有字符串按顺序写入文件。同样,它也不会自动添加换行符,如果需要每写入一个元素就换行,列表中的每个字符串都应包含 ``。
lines_to_write = [
"列表写入的第一行。",
"列表写入的第二行。",
"列表写入的第三行。"
]
with open('', 'w', encoding='utf-8') as f:
(lines_to_write)
# 验证内容
with open('', 'r', encoding='utf-8') as f:
print("--- 内容 ---")
print(())

3. 追加内容到文件('a' 模式)


使用 `'a'` 模式,可以将新内容添加到文件的末尾,而不会覆盖原有内容。
# 初始写入
with open('', 'w', encoding='utf-8') as f:
("原始内容。")
# 追加内容
with open('', 'a', encoding='utf-8') as f:
("这是追加的第一行。")
("这是追加的第二行。")
# 验证内容
with open('', 'r', encoding='utf-8') as f:
print("--- 内容 ---")
print(())

六、文件编码(Encoding)的重要性

文件编码是文件操作中一个极其容易被忽视但又非常关键的环节。文本文件实际上存储的是一系列二进制字节,而编码(如 UTF-8, GBK, Latin-1 等)定义了这些字节如何映射到人类可读的字符。如果读写文件的编码不一致,就会出现“乱码”问题(`UnicodeDecodeError`)。

最佳实践:始终明确指定 `encoding='utf-8'`。

UTF-8 是一种通用的、兼容性最好的编码格式,支持世界上几乎所有的字符。在大多数情况下,使用 UTF-8 可以避免跨平台或跨语言的乱码问题。
# 写入一个使用 GBK 编码的文件 (仅作演示,不推荐常规使用)
try:
with open('', 'w', encoding='gbk') as f:
("你好,世界!这是GBK编码。")
print("GBK文件写入成功。")
except Exception as e:
print(f"写入GBK文件时发生错误: {e}")
# 尝试以 UTF-8 读取 GBK 文件,会引发 UnicodeDecodeError
try:
with open('', 'r', encoding='utf-8') as f:
content = ()
print("尝试以UTF-8读取GBK文件:", content)
except UnicodeDecodeError as e:
print(f"解码错误:无法以UTF-8解码GBK文件 - {e}")
# 以正确的 GBK 编码读取
try:
with open('', 'r', encoding='gbk') as f:
content = ()
print("以GBK正确读取:", content)
except Exception as e:
print(f"读取GBK文件时发生错误: {e}")

当遇到编码错误时,`errors` 参数可以帮助我们处理:
`errors='strict'` (默认):遇到编码错误时抛出 `UnicodeDecodeError`。
`errors='ignore'`:忽略无法解码的字符。这可能导致数据丢失。
`errors='replace'`:用一个特殊的替换字符(通常是 `U+FFFD` �)代替无法解码的字符。

七、错误处理:让文件操作更健壮

文件操作常常伴随着各种潜在的错误,例如文件不存在、没有权限、磁盘空间不足等。使用 `try...except` 块来捕获和处理这些异常,是编写健壮代码的关键。
file_name = ''
try:
with open(file_name, 'r', encoding='utf-8') as f:
content = ()
print(f"文件 '{file_name}' 内容:{content}")
except FileNotFoundError:
print(f"错误: 文件 '{file_name}' 不存在,无法读取。")
except PermissionError:
print(f"错误: 没有权限访问文件 '{file_name}'。")
except UnicodeDecodeError:
print(f"错误: 文件 '{file_name}' 的编码不正确,无法解码。")
except IOError as e: # 捕获其他I/O相关错误
print(f"I/O错误: 无法操作文件 '{file_name}' - {e}")
except Exception as e: # 捕获所有其他未知错误
print(f"发生未知错误: {e}")
# 尝试写入一个不允许写入的路径(例如系统目录)
try:
with open('/root/', 'w', encoding='utf-8') as f: # 在非root用户下会失败
("尝试写入受保护的路径。")
except PermissionError:
print("错误: 尝试写入受保护的系统目录,权限不足。")
except Exception as e:
print(f"写入时发生其他错误: {e}")

八、文件路径:相对路径与绝对路径

文件路径有两种形式:
相对路径: 相对于当前工作目录的路径。例如,`''` 表示当前目录下的 ``,`'subfolder/'` 表示当前目录下的 `subfolder` 文件夹中的 ``。
绝对路径: 从文件系统的根目录开始的完整路径。例如,在 Windows 上是 `'C:Users\User\Documents\'`,在 Linux/macOS 上是 `'/home/user/documents/'`。

为了提高代码的可移植性,尤其是在处理跨平台文件路径时,推荐使用 `` 模块:
import os
# 获取当前工作目录
current_dir = ()
print(f"当前工作目录: {current_dir}")
# 构建跨平台兼容的路径
file_name = ''
folder_name = 'data'
full_path = (current_dir, folder_name, file_name)
print(f"构建的完整路径: {full_path}")
# 检查文件或目录是否存在
if (full_path):
print(f"路径 '{full_path}' 存在。")
else:
print(f"路径 '{full_path}' 不存在。")
# 如果目录不存在,可以创建它
if not ((current_dir, folder_name)):
((current_dir, folder_name))
print(f"创建了目录: {(current_dir, folder_name)}")
# 示例:写入到指定目录下的文件
try:
with open(full_path, 'w', encoding='utf-8') as f:
("这是写入到指定目录下的文件内容。")
print(f"成功写入文件: {full_path}")
except Exception as e:
print(f"写入文件时发生错误: {e}")

九、处理大型TXT文件

对于G级别甚至更大的TXT文件,一次性加载到内存中是不可取的,会导致内存溢出。Python 的迭代文件对象机制在这里发挥了关键作用。

1. 逐行处理


如前所述,直接迭代文件对象是最内存高效的方式。
def process_large_file(filepath):
line_count = 0
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
# 在这里处理每一行数据,例如:
# print(f"处理行: {()}")
line_count += 1
if line_count % 100000 == 0:
print(f"已处理 {line_count} 行...")
print(f"文件 '{filepath}' 处理完毕,总行数: {line_count}")
# 假设有一个名为 '' 的大型文件
# process_large_file('')

2. 分块读取(read(size))


有时我们需要按固定大小的块而不是按行处理文件(例如,处理没有明确行结束符的二进制数据,或者需要在一个循环中处理固定字节块的文本数据)。
def read_in_chunks(filepath, chunk_size=4096): # 4KB
with open(filepath, 'r', encoding='utf-8') as f:
while True:
chunk = (chunk_size)
if not chunk:
break
# 在这里处理 chunk,例如:
# print(f"读取到 {len(chunk)} 字符的块:{chunk[:50]}...")
# 注意:如果chunk截断了一个多字节字符,可能会出现问题。对于文本,通常按行迭代更安全。
pass
# read_in_chunks('')

十、高级操作:tell() 和 seek()

文件对象还提供了 `tell()` 和 `seek()` 方法,用于获取和设置文件指针的当前位置。
`tell()`:返回文件指针当前的位置(从文件开头算起的字节偏移量)。
`seek(offset, whence=0)`:将文件指针移动到指定位置。

`offset`:偏移量。
`whence`:起始位置。`0` 表示从文件开头(默认),`1` 表示从当前位置,`2` 表示从文件末尾。




with open('', 'w+', encoding='utf-8') as f:
("Hello, Python!")
print(f"当前指针位置: {()}") # 14 (UTF-8中一个英文字符一个字节)
(7) # 移动到 "Python!" 的 'P'
print(f"移动后指针位置: {()}") # 7
content_from_seek = ()
print(f"从指针位置读取: {content_from_seek}") # Python!
(0) # 移回文件开头
first_char = (1)
print(f"文件开头第一个字符: {first_char}") # H
(0, 2) # 移动到文件末尾
(" 这是追加的内容。")
(0)
print(f"追加后内容: {()}") # Hello, Python! 这是追加的内容。

需要注意的是,在使用 `seek()` 和 `tell()` 时,`offset` 总是以字节为单位。在文本模式下,由于字符编码的复杂性(例如,UTF-8 中的一个字符可能由1到4个字节组成),直接在文本模式下使用 `seek()` 进行精确的字符定位可能会比较复杂,通常更适用于二进制模式。

十一、总结

Python 提供了强大而灵活的工具来处理 TXT 文件。掌握 `open()` 函数、各种文件模式、读取和写入方法,以及最重要的 `with` 语句,是进行文件操作的基础。此外,对文件编码的深刻理解、健壮的错误处理以及对大型文件的内存管理策略,都是成为一名专业程序员必备的技能。希望本文能帮助你全面掌握 Python TXT 文件操作,并在实际项目中高效、安全地处理文本数据。

2025-11-07


上一篇:Python图片爬取实战:从入门到高效下载海量图像数据

下一篇:Python数据与JavaScript交互:从后端到前端的深度实践指南