第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}')

十、总结

本集学习了文本文件操作的高级知识:

  • 文本文件编码的重要性和常用编码方式
  • 如何处理编码错误
  • 大文本文件的处理技巧
  • 文本文件的格式化和解析
  • 文本文件处理的常见问题和最佳实践

掌握这些技能后,可以更高效地处理各种文本文件。下一集我们将学习二进制文件操作。

十一、练习题

  1. 创建一个UTF-8编码的文本文件,写入中英文混合内容,然后读取并显示。
  2. 编写一个函数,统计文本文件中的行数、字符数、单词数。
  3. 实现一个函数,在文件中查找并替换指定的文本。
  4. 编写一个程序,合并多个文本文件到一个文件中。
  5. 实现一个函数,解析键值对格式的配置文件。
  6. 处理一个大文本文件,逐行读取并过滤掉空行和注释行。
  7. 编写一个程序,将CSV格式的文本文件转换为JSON格式。
  8. 实现一个日志文件分析器,统计不同级别的日志数量。
« 上一篇 文件读写基础 下一篇 » 二进制文件操作