第82集:文本文件操作
学习目标
- 深入理解文本文件的编码方式
- 掌握不同编码格式的文件读写
- 学会处理大文本文件的技巧
- 掌握文本文件的格式化和解析
- 学会处理文本文件中的常见问题
一、文本文件编码
1.1 什么是字符编码
字符编码是将字符转换为字节序列的规则。常见的编码方式包括:
- UTF-8:可变长度编码,支持全球所有字符,推荐使用
- GBK:中文编码,主要用于简体中文Windows系统
- GB2312:简体中文编码,GBK的子集
- ASCII:美国信息交换标准代码,仅支持英文字符
1.2 编码的重要性
在读写文本文件时,必须使用正确的编码方式,否则会出现乱码或解码错误。
# 使用UTF-8编码写入
with open('file.txt', 'w', encoding='utf-8') as f:
f.write('你好,世界!')
# 使用UTF-8编码读取
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()二、指定编码方式
2.1 open()函数的encoding参数
open(file, mode='r', encoding=None)2.2 常用编码方式示例
# UTF-8编码(推荐)
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
# GBK编码(中文Windows默认)
with open('file.txt', 'r', encoding='gbk') as f:
content = f.read()
# GB2312编码
with open('file.txt', 'r', encoding='gb2312') as f:
content = f.read()三、处理编码错误
3.1 UnicodeDecodeError
当使用错误的编码方式读取文件时,会抛出UnicodeDecodeError。
# 错误示例:用GBK读取UTF-8编码的文件
try:
with open('utf8_file.txt', 'r', encoding='gbk') as f:
content = f.read()
except UnicodeDecodeError as e:
print(f"解码错误:{e}")3.2 errors参数处理编码错误
errors参数可以指定如何处理编码错误:
| errors值 | 描述 |
|---|---|
| 'strict' | 严格模式,遇到错误抛出异常(默认) |
| 'ignore' | 忽略错误,跳过无法解码的字符 |
| 'replace' | 用替换字符(�)替代无法解码的字符 |
| 'backslashreplace' | 用反斜杠转义序列替代无法解码的字符 |
# 忽略编码错误
with open('file.txt', 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# 使用替换字符
with open('file.txt', 'r', encoding='utf-8', errors='replace') as f:
content = f.read()四、大文本文件处理
4.1 逐行读取大文件
对于大文件,不要一次性读取整个文件,应该逐行读取。
# 推荐方式:逐行读取
with open('large_file.txt', 'r', encoding='utf-8') as f:
for line in f:
process(line) # 处理每一行4.2 分块读取大文件
使用read(size)方法分块读取文件。
# 分块读取,每次读取4096字节
with open('large_file.txt', 'r', encoding='utf-8') as f:
while True:
chunk = f.read(4096)
if not chunk:
break
process(chunk) # 处理每个块4.3 使用生成器处理大文件
创建生成器函数来惰性读取大文件。
def read_large_file(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
yield line
# 使用生成器
for line in read_large_file('large_file.txt'):
process(line)五、文本文件格式化
5.1 写入格式化文本
使用字符串格式化方法写入格式化文本。
# 使用f-string格式化
name = '张三'
age = 25
with open('user_info.txt', 'w', encoding='utf-8') as f:
f.write(f'姓名:{name}\n')
f.write(f'年龄:{age}\n')
f.write(f'出生年份:{2024 - age}\n')5.2 使用format()方法
with open('report.txt', 'w', encoding='utf-8') as f:
f.write('成绩报告\n')
f.write('=' * 20 + '\n')
f.write('姓名:{}\n'.format('李四'))
f.write('数学:{}\n'.format(95))
f.write('英语:{}\n'.format(88))5.3 使用%格式化
with open('log.txt', 'w', encoding='utf-8') as f:
f.write('时间:%s\n' % '2024-01-01 12:00:00')
f.write('级别:%s\n' % 'INFO')
f.write('消息:%s\n' % '程序启动成功')六、文本文件解析
6.1 解析CSV格式文本
虽然Python有专门的csv模块,但简单的CSV文本可以手动解析。
# 解析CSV格式文本
with open('data.csv', 'r', encoding='utf-8') as f:
for line in f:
fields = line.strip().split(',')
print(fields)6.2 解析键值对格式
# 解析键值对格式(key=value)
config = {}
with open('config.txt', 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line and '=' in line:
key, value = line.split('=', 1)
config[key.strip()] = value.strip()6.3 解析JSON格式文本
使用json模块解析JSON格式文本。
import json
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print(data)6.4 解析INI格式文本
# 简单的INI格式解析
config = {}
current_section = None
with open('config.ini', 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
# 跳过空行和注释
if not line or line.startswith('#') or line.startswith(';'):
continue
# 处理节
if line.startswith('[') and line.endswith(']'):
current_section = line[1:-1]
config[current_section] = {}
# 处理键值对
elif '=' in line and current_section:
key, value = line.split('=', 1)
config[current_section][key.strip()] = value.strip()七、文本文件处理技巧
7.1 去除空白字符
使用strip()、lstrip()、rstrip()方法去除空白字符。
with open('file.txt', 'r', encoding='utf-8') as f:
for line in f:
line = line.strip() # 去除首尾空白
if line: # 跳过空行
print(line)7.2 统计文本信息
# 统计文件行数、字符数、单词数
with open('file.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
line_count = len(lines)
char_count = sum(len(line) for line in lines)
word_count = sum(len(line.split()) for line in lines)
print(f'行数:{line_count}')
print(f'字符数:{char_count}')
print(f'单词数:{word_count}')7.3 查找和替换文本
# 在文件中查找并替换文本
def replace_in_file(file_path, old_text, new_text):
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
content = content.replace(old_text, new_text)
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
replace_in_file('file.txt', '旧文本', '新文本')7.4 合并多个文本文件
# 合并多个文本文件
def merge_files(output_file, input_files):
with open(output_file, 'w', encoding='utf-8') as out_f:
for input_file in input_files:
with open(input_file, 'r', encoding='utf-8') as in_f:
out_f.write(in_f.read())
out_f.write('\n') # 文件之间添加换行
merge_files('merged.txt', ['file1.txt', 'file2.txt', 'file3.txt'])八、文本文件常见问题
8.1 换行符问题
不同操作系统使用不同的换行符:
- Windows:
\r\n - Linux/Mac:
\n - 旧版Mac:
\r
Python会自动处理换行符,但在某些情况下需要注意。
# 读取时统一换行符
with open('file.txt', 'r', encoding='utf-8', newline='') as f:
content = f.read()
# 写入时指定换行符
with open('file.txt', 'w', encoding='utf-8', newline='\n') as f:
f.write('第一行\n第二行\n')8.2 BOM(字节顺序标记)
某些UTF-8文件开头可能有BOM标记,需要特殊处理。
# 处理带BOM的UTF-8文件
with open('file.txt', 'r', encoding='utf-8-sig') as f:
content = f.read()8.3 文件路径问题
# 使用原始字符串处理Windows路径
file_path = r'C:\Users\用户名\Documents\file.txt'
# 使用os.path处理跨平台路径
import os
file_path = os.path.join('folder', 'subfolder', 'file.txt')九、最佳实践
9.1 始终指定编码方式
# 推荐
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
# 不推荐(依赖系统默认编码)
with open('file.txt', 'r') as f:
content = f.read()9.2 使用with语句
# 推荐
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
# 不推荐
f = open('file.txt', 'r', encoding='utf-8')
content = f.read()
f.close()9.3 处理大文件时逐行读取
# 推荐
with open('large_file.txt', 'r', encoding='utf-8') as f:
for line in f:
process(line)
# 不推荐(可能内存溢出)
with open('large_file.txt', 'r', encoding='utf-8') as f:
content = f.read() # 一次性读取整个文件9.4 异常处理
try:
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
except FileNotFoundError:
print('文件不存在')
except UnicodeDecodeError:
print('编码错误,请检查文件编码')
except Exception as e:
print(f'发生错误:{e}')十、总结
本集学习了文本文件操作的高级知识:
- 文本文件编码的重要性和常用编码方式
- 如何处理编码错误
- 大文本文件的处理技巧
- 文本文件的格式化和解析
- 文本文件处理的常见问题和最佳实践
掌握这些技能后,可以更高效地处理各种文本文件。下一集我们将学习二进制文件操作。
十一、练习题
- 创建一个UTF-8编码的文本文件,写入中英文混合内容,然后读取并显示。
- 编写一个函数,统计文本文件中的行数、字符数、单词数。
- 实现一个函数,在文件中查找并替换指定的文本。
- 编写一个程序,合并多个文本文件到一个文件中。
- 实现一个函数,解析键值对格式的配置文件。
- 处理一个大文本文件,逐行读取并过滤掉空行和注释行。
- 编写一个程序,将CSV格式的文本文件转换为JSON格式。
- 实现一个日志文件分析器,统计不同级别的日志数量。