目录

Python 文件读写

学习目标

  • 掌握文件的打开、读取和写入操作
  • 理解不同的文件模式
  • 学会处理文本文件和二进制文件
  • 掌握文件编码和常见文件格式处理

1. 打开文件

1.1 open() 函数

# 基本语法
# open(file, mode='r', encoding=None, ...)

# 读取文本文件
f = open('data.txt', 'r', encoding='utf-8')
content = f.read()
f.close()

# 推荐:使用 with 语句(自动关闭)
with open('data.txt', 'r', encoding='utf-8') as f:
    content = f.read()
# 文件已自动关闭

1.2 文件模式

模式 说明
'r' 读取(默认)
'w' 写入,会覆盖原有内容
'x' 独占创建,文件已存在则报错
'a' 追加写入
'b' 二进制模式
't' 文本模式(默认)
'+' 读写模式
# 常用模式组合
'r'   # 只读文本
'w'   # 只写文本(覆盖)
'a'   # 追加文本
'rb'  # 只读二进制
'wb'  # 只写二进制
'r+'  # 读写(文件必须存在)
'w+'  # 读写(覆盖或创建)

2. 读取文件

2.1 读取整个文件

with open('example.txt', 'r', encoding='utf-8') as f:
    content = f.read()  # 读取全部内容
    print(content)

2.2 逐行读取

# 方法1:readlines()
with open('example.txt', 'r', encoding='utf-8') as f:
    lines = f.readlines()  # 返回列表
    for line in lines:
        print(line.strip())

# 方法2:直接迭代(推荐,内存友好)
with open('example.txt', 'r', encoding='utf-8') as f:
    for line in f:
        print(line.strip())

# 方法3:readline() 逐行
with open('example.txt', 'r', encoding='utf-8') as f:
    while True:
        line = f.readline()
        if not line:
            break
        print(line.strip())

2.3 指定读取大小

with open('example.txt', 'r', encoding='utf-8') as f:
    # 读取前100个字符
    chunk = f.read(100)
    print(f"前100个字符: {chunk}")
    
    # 继续读取
    chunk2 = f.read(100)
    print(f"接下来100个字符: {chunk2}")

3. 写入文件

3.1 写入文本

# 覆盖写入
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write('第一行\n')
    f.write('第二行\n')

# 追加写入
with open('output.txt', 'a', encoding='utf-8') as f:
    f.write('第三行(追加)\n')

# 写入多行
lines = ['行1\n', '行2\n', '行3\n']
with open('output.txt', 'w', encoding='utf-8') as f:
    f.writelines(lines)

3.2 print 重定向到文件

with open('log.txt', 'w', encoding='utf-8') as f:
    print('日志信息1', file=f)
    print('日志信息2', file=f)
    print('带变量:', 42, file=f)

4. 二进制文件操作

4.1 读写二进制

# 写入二进制数据
data = bytes([0, 1, 2, 255])
with open('binary.bin', 'wb') as f:
    f.write(data)

# 读取二进制数据
with open('binary.bin', 'rb') as f:
    data = f.read()
    print(data)  # b'\x00\x01\x02\xff'
    print(list(data))  # [0, 1, 2, 255]

4.2 复制文件

def copy_file(src, dst):
    """复制文件"""
    with open(src, 'rb') as f_src:
        with open(dst, 'wb') as f_dst:
            while True:
                chunk = f_src.read(4096)  # 分块读取
                if not chunk:
                    break
                f_dst.write(chunk)

# 使用
copy_file('source.jpg', 'backup.jpg')

5. 文件指针操作

with open('data.txt', 'r+', encoding='utf-8') as f:
    # 读取前10个字符
    print(f.read(10))
    
    # 获取当前位置
    print(f"当前位置: {f.tell()}")
    
    # 移动到文件开头
    f.seek(0)
    print(f"回到开头后: {f.read(5)}")
    
    # seek(offset, whence)
    # whence: 0=开头(默认), 1=当前位置, 2=文件末尾
    f.seek(0, 2)  # 移动到末尾
    print(f"文件大小: {f.tell()}")

6. 编码处理

6.1 指定编码

# UTF-8(推荐)
with open('utf8.txt', 'w', encoding='utf-8') as f:
    f.write('中文内容')

# GBK
with open('gbk.txt', 'w', encoding='gbk') as f:
    f.write('中文内容')

# 读取时指定编码
with open('gbk.txt', 'r', encoding='gbk') as f:
    print(f.read())

6.2 自动检测编码

# 使用 chardet 库检测编码(需安装: pip install chardet)
# import chardet
# 
# with open('unknown.txt', 'rb') as f:
#     result = chardet.detect(f.read())
#     print(result)  # {'encoding': 'UTF-8', 'confidence': 0.99}

6.3 处理编码错误

# 忽略错误字符
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()

# 严格模式(默认,遇到错误抛出异常)
with open('file.txt', 'r', encoding='utf-8', errors='strict') as f:
    content = f.read()

7. 常见文件格式处理

7.1 CSV 文件

import csv

# 写入 CSV
with open('data.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(['姓名', '年龄', '城市'])
    writer.writerow(['Alice', 25, '北京'])
    writer.writerow(['Bob', 30, '上海'])

# 读取 CSV
with open('data.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

# 使用 DictReader
with open('data.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['姓名']}: {row['年龄']}岁")

7.2 JSON 文件

import json

data = {
    "name": "Alice",
    "age": 25,
    "hobbies": ["读书", "游泳"]
}

# 写入 JSON
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

# 读取 JSON
with open('data.json', 'r', encoding='utf-8') as f:
    loaded = json.load(f)
    print(loaded)

# JSON 字符串
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)

parsed = json.loads(json_str)
print(parsed)

7.3 临时文件

import tempfile

# 创建临时文件
with tempfile.TemporaryFile(mode='w+', encoding='utf-8') as f:
    f.write('临时数据')
    f.seek(0)
    print(f.read())
# 文件自动删除

# 创建有名临时文件
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
    f.write('有名临时文件')
    print(f"临时文件路径: {f.name}")
# 需要手动删除

# 临时目录
with tempfile.TemporaryDirectory() as tmpdir:
    print(f"临时目录: {tmpdir}")
    # 在目录中创建文件...
# 目录自动删除

8. 文件和目录操作

import os
import shutil

# 文件操作
os.rename('old.txt', 'new.txt')       # 重命名
os.remove('file.txt')                 # 删除文件
shutil.copy('src.txt', 'dst.txt')     # 复制文件
shutil.move('src.txt', 'dst/')        # 移动文件

# 检查文件
print(os.path.exists('file.txt'))     # 是否存在
print(os.path.isfile('file.txt'))     # 是否是文件
print(os.path.getsize('file.txt'))    # 文件大小

# 路径操作
print(os.path.join('folder', 'file.txt'))  # folder/file.txt
print(os.path.abspath('file.txt'))         # 绝对路径
print(os.path.dirname('/a/b/c.txt'))       # /a/b
print(os.path.basename('/a/b/c.txt'))      # c.txt
print(os.path.splitext('file.txt'))        # ('file', '.txt')

本节小结

  • 打开文件:使用 with 语句自动管理资源
  • 文件模式r/w/a/x 配合 b/t/+ 满足各种需求
  • 读取方式read()readline()、迭代文件对象
  • 编码处理:始终显式指定 encoding='utf-8'
  • 常见格式csvjson 使用标准库处理
  • 临时文件tempfile 模块安全创建临时资源

练习

  1. 编写一个函数,统计文本文件的行数、单词数和字符数
  2. 实现一个配置文件解析器,支持 JSON 和 CSV 格式
  3. 编写程序合并多个文本文件,并去除重复行
  4. 创建一个日志文件处理器,自动按日期分割日志文件