Python 文件操作详解与代码示例

文章目录

  • [Python 文件操作详解与代码示例](#Python 文件操作详解与代码示例)
    • 一、文件操作基础
      • [1. 打开和关闭文件](#1. 打开和关闭文件)
      • [2. 文件读取方法](#2. 文件读取方法)
      • [3. 文件写入方法](#3. 文件写入方法)
    • 二、高级文件操作
      • [1. 文件路径操作](#1. 文件路径操作)
      • [2. 上下文管理和文件操作](#2. 上下文管理和文件操作)
      • [3. 文件编码和格式处理](#3. 文件编码和格式处理)
    • 三、实际应用示例
      • [1. 日志文件分析器](#1. 日志文件分析器)
      • [2. 配置文件管理器](#2. 配置文件管理器)
      • [3. 文件备份和同步工具](#3. 文件备份和同步工具)
    • 四、最佳实践和性能优化
    • 总结
      • Python文件操作要点:
      • [📝 核心操作与代码示例](#📝 核心操作与代码示例)
        • [1. 基础文本文件读写](#1. 基础文本文件读写)
        • [2. 二进制文件读写](#2. 二进制文件读写)
        • [3. 文件指针与随机访问](#3. 文件指针与随机访问)
      • [🚀 现代C++的增强特性](#🚀 现代C++的增强特性)
        • [1. 使用 `std::filesystem` (C++17)](#1. 使用 std::filesystem (C++17))
        • [2. 结合 `std::string_view` 和 `std::format` (C++17/20)](#2. 结合 std::string_viewstd::format (C++17/20))
      • [💡 最佳实践与要点](#💡 最佳实践与要点)

Python 文件操作详解与代码示例

一、文件操作基础

1. 打开和关闭文件

python 复制代码
# ==================== 基本的文件打开和关闭 ====================

def basic_file_operations():
    print("=== 基本文件操作 ===")
    
    # 1. 使用 open() 函数打开文件
    # 模式说明:
    # 'r' - 只读(默认)
    # 'w' - 写入,会覆盖已有内容
    # 'a' - 追加,在文件末尾添加内容
    # 'x' - 创建新文件,如果文件已存在则失败
    # 'b' - 二进制模式
    # 't' - 文本模式(默认)
    # '+' - 读写模式
    
    # 方法1:传统的打开和关闭方式
    print("方法1:传统方式")
    file = None
    try:
        # 打开文件进行读取
        file = open('test.txt', 'w', encoding='utf-8')  # 写入模式
        file.write("Hello, World!\n")
        file.write("这是测试文件\n")
        print("文件写入成功")
    except IOError as e:
        print(f"文件操作错误: {e}")
    finally:
        # 确保文件被关闭
        if file and not file.closed:
            file.close()
            print("文件已关闭")
    
    # 方法2:使用 with 语句(推荐)
    # with 语句会自动管理文件资源,确保文件被正确关闭
    print("\n方法2:使用 with 语句(推荐)")
    try:
        with open('test.txt', 'r', encoding='utf-8') as file:
            content = file.read()
            print(f"文件内容:\n{content}")
    except FileNotFoundError:
        print("文件不存在")
    except IOError as e:
        print(f"读取文件时出错: {e}")
    
    # 2. 不同的打开模式
    print("\n=== 不同的打开模式 ===")
    
    # 写入模式(如果文件不存在则创建,存在则覆盖)
    with open('example.txt', 'w', encoding='utf-8') as f:
        f.write("第一行\n")
        f.write("第二行\n")
    
    # 追加模式
    with open('example.txt', 'a', encoding='utf-8') as f:
        f.write("追加的内容\n")
    
    # 读取模式
    with open('example.txt', 'r', encoding='utf-8') as f:
        print(f"example.txt 内容:\n{f.read()}")
    
    # 读写模式(r+)
    with open('example.txt', 'r+', encoding='utf-8') as f:
        content = f.read()
        f.write("使用r+模式添加的内容\n")
        print(f"r+模式读取的内容:\n{content}")
    
    # 创建新文件模式(x)
    try:
        with open('new_file.txt', 'x', encoding='utf-8') as f:
            f.write("这是一个新文件\n")
            print("新文件创建成功")
    except FileExistsError:
        print("文件已存在,x模式会失败")
    
    # 3. 检查文件状态
    print("\n=== 文件状态检查 ===")
    
    file_path = 'example.txt'
    
    # 检查文件是否存在
    import os
    if os.path.exists(file_path):
        print(f"文件 {file_path} 存在")
        
        # 获取文件大小
        file_size = os.path.getsize(file_path)
        print(f"文件大小: {file_size} 字节")
        
        # 获取文件修改时间
        import time
        mod_time = os.path.getmtime(file_path)
        print(f"最后修改时间: {time.ctime(mod_time)}")
        
        # 检查是否为文件
        print(f"是否为文件: {os.path.isfile(file_path)}")
        
        # 检查是否为目录
        print(f"是否为目录: {os.path.isdir(file_path)}")
    else:
        print(f"文件 {file_path} 不存在")
    
    # 4. 文件属性
    print("\n=== 文件属性 ===")
    with open('example.txt', 'r', encoding='utf-8') as f:
        print(f"文件名称: {f.name}")
        print(f"文件模式: {f.mode}")
        print(f"文件编码: {f.encoding}")
        print(f"文件是否已关闭: {f.closed}")
    
    print(f"with语句块外文件是否已关闭: {f.closed}")

basic_file_operations()

2. 文件读取方法

python 复制代码
# ==================== 文件读取方法 ====================

def file_reading_methods():
    print("\n=== 文件读取方法 ===")
    
    # 先创建一个测试文件
    with open('data.txt', 'w', encoding='utf-8') as f:
        for i in range(1, 11):
            f.write(f"第{i}行: 这是测试数据 {i}\n")
    
    print("测试文件 data.txt 已创建\n")
    
    # 1. read() - 读取整个文件
    print("1. read() - 读取整个文件:")
    with open('data.txt', 'r', encoding='utf-8') as f:
        content = f.read()
        print(f"读取前5个字符: {content[:50]}...")
        print(f"总字符数: {len(content)}")
    
    # 2. read(size) - 读取指定大小的内容
    print("\n2. read(size) - 读取指定大小:")
    with open('data.txt', 'r', encoding='utf-8') as f:
        # 读取前100个字符
        chunk = f.read(100)
        print(f"读取100个字符:\n{chunk}")
        
        # 继续读取下一个100字符
        chunk2 = f.read(100)
        print(f"继续读取100个字符:\n{chunk2}")
        
        # 检查文件指针位置
        position = f.tell()
        print(f"当前文件指针位置: {position}")
        
        # 回到文件开头
        f.seek(0)
        print(f"回到开头后指针位置: {f.tell()}")
    
    # 3. readline() - 读取一行
    print("\n3. readline() - 逐行读取:")
    with open('data.txt', 'r', encoding='utf-8') as f:
        line1 = f.readline()
        line2 = f.readline()
        print(f"第一行: {line1.strip()}")
        print(f"第二行: {line2.strip()}")
    
    # 4. readlines() - 读取所有行到列表
    print("\n4. readlines() - 读取所有行到列表:")
    with open('data.txt', 'r', encoding='utf-8') as f:
        lines = f.readlines()
        print(f"总行数: {len(lines)}")
        print(f"前3行:")
        for i, line in enumerate(lines[:3], 1):
            print(f"  行{i}: {line.strip()}")
    
    # 5. 遍历文件对象(逐行读取,内存高效)
    print("\n5. 遍历文件对象(内存高效):")
    with open('data.txt', 'r', encoding='utf-8') as f:
        line_count = 0
        for line in f:
            line_count += 1
            if line_count <= 3:
                print(f"  行{line_count}: {line.strip()}")
        print(f"  总行数: {line_count}")
    
    # 6. 使用 with 语句和异常处理
    print("\n6. 文件读取的异常处理:")
    
    def read_file_safely(filename):
        """安全读取文件的函数"""
        try:
            with open(filename, 'r', encoding='utf-8') as f:
                return f.read()
        except FileNotFoundError:
            return f"错误: 文件 '{filename}' 不存在"
        except PermissionError:
            return f"错误: 没有权限读取文件 '{filename}'"
        except UnicodeDecodeError:
            return f"错误: 文件 '{filename}' 编码问题"
        except Exception as e:
            return f"错误: 读取文件时发生未知错误 - {e}"
    
    # 测试各种情况
    print(read_file_safely('data.txt'))
    print(read_file_safely('nonexistent.txt'))
    
    # 7. 大文件读取策略
    print("\n7. 大文件读取策略:")
    
    def process_large_file(filename, chunk_size=1024):
        """分块读取大文件"""
        print(f"分块读取 {filename},每块 {chunk_size} 字节")
        
        with open(filename, 'r', encoding='utf-8') as f:
            chunk_count = 0
            total_chars = 0
            
            while True:
                chunk = f.read(chunk_size)
                if not chunk:  # 读取完毕
                    break
                
                chunk_count += 1
                total_chars += len(chunk)
                
                if chunk_count <= 2:  # 只显示前两块
                    print(f"  第{chunk_count}块({len(chunk)}字符): {chunk[:50]}...")
            
            print(f"  总共读取 {chunk_count} 块,{total_chars} 字符")
    
    # 创建一个稍大的文件
    with open('large_data.txt', 'w', encoding='utf-8') as f:
        for i in range(100):
            f.write(f"这是第{i+1}行数据,包含一些测试内容以便生成足够长的行。\n")
    
    process_large_file('large_data.txt', 200)
    
    # 8. 带缓冲区的读取
    print("\n8. 带缓冲区的读取:")
    
    # 创建二进制文件
    with open('binary_data.bin', 'wb') as f:
        f.write(b'Hello' * 1000)  # 5000字节的二进制数据
    
    # 使用缓冲区读取
    buffer_size = 512
    with open('binary_data.bin', 'rb') as f:
        chunk = f.read(buffer_size)
        print(f"读取 {len(chunk)} 字节: {chunk[:20]}...")
    
    # 9. 读取特定位置的内容
    print("\n9. 读取特定位置的内容:")
    with open('data.txt', 'r', encoding='utf-8') as f:
        # 跳转到第50个字节
        f.seek(50)
        content = f.read(50)
        print(f"从位置50读取50字节:\n{content}")
        
        # 获取当前位置
        current = f.tell()
        print(f"当前位置: {current}")
        
        # 相对当前位置移动
        f.seek(-20, 1)  # 从当前位置向前移动20字节
        print(f"向前移动20字节后位置: {f.tell()}")
        
        # 从文件末尾移动
        f.seek(-30, 2)  # 从文件末尾向前移动30字节
        print(f"从文件末尾向前30字节位置: {f.tell()}")
        print(f"最后30字节内容: {f.read()}")

file_reading_methods()

3. 文件写入方法

python 复制代码
# ==================== 文件写入方法 ====================

def file_writing_methods():
    print("\n=== 文件写入方法 ===")
    
    # 1. write() - 写入字符串
    print("1. write() - 写入字符串:")
    with open('write_test.txt', 'w', encoding='utf-8') as f:
        f.write("这是第一行\n")
        f.write("这是第二行\n")
        f.write("数字: " + str(123) + "\n")
        f.write(f"格式化字符串: {3.14:.2f}\n")
    
    # 验证写入内容
    with open('write_test.txt', 'r', encoding='utf-8') as f:
        print(f"写入的内容:\n{f.read()}")
    
    # 2. writelines() - 写入字符串列表
    print("\n2. writelines() - 写入字符串列表:")
    lines = [
        "使用writelines写入\n",
        "这是列表中的第一行\n",
        "这是列表中的第二行\n",
        "不需要手动添加换行符,但列表中的字符串可以包含\n"
    ]
    
    with open('writelines_test.txt', 'w', encoding='utf-8') as f:
        f.writelines(lines)
    
    # 验证
    with open('writelines_test.txt', 'r', encoding='utf-8') as f:
        print(f"writelines写入的内容:\n{f.read()}")
    
    # 3. 追加模式
    print("\n3. 追加模式:")
    with open('append_test.txt', 'w', encoding='utf-8') as f:
        f.write("初始内容\n")
    
    # 多次追加
    for i in range(3):
        with open('append_test.txt', 'a', encoding='utf-8') as f:
            f.write(f"第{i+1}次追加的内容\n")
    
    with open('append_test.txt', 'r', encoding='utf-8') as f:
        print(f"追加后的内容:\n{f.read()}")
    
    # 4. 读写模式(r+)
    print("\n4. 读写模式(r+):")
    with open('rplus_test.txt', 'w', encoding='utf-8') as f:
        f.write("第一行\n第二行\n第三行\n")
    
    with open('rplus_test.txt', 'r+', encoding='utf-8') as f:
        # 读取内容
        content = f.read()
        print(f"原始内容:\n{content}")
        
        # 移动到文件开头
        f.seek(0)
        
        # 写入新内容(会覆盖原有内容)
        f.write("新第一行\n")
        
        # 移动到文件末尾
        f.seek(0, 2)
        
        # 追加内容
        f.write("追加的内容\n")
    
    with open('rplus_test.txt', 'r', encoding='utf-8') as f:
        print(f"修改后的内容:\n{f.read()}")
    
    # 5. 二进制写入
    print("\n5. 二进制写入:")
    # 创建一些二进制数据
    binary_data = bytes(range(256))  # 0-255的字节
    
    with open('binary_write.bin', 'wb') as f:
        f.write(binary_data)
    
    # 读取验证
    with open('binary_write.bin', 'rb') as f:
        read_data = f.read(10)  # 读取前10个字节
        print(f"前10个字节: {read_data}")
        print(f"文件大小: {len(binary_data)} 字节")
    
    # 6. 结构化数据写入
    print("\n6. 结构化数据写入:")
    
    # 写入CSV格式
    data = [
        ["姓名", "年龄", "城市"],
        ["张三", "25", "北京"],
        ["李四", "30", "上海"],
        ["王五", "28", "广州"]
    ]
    
    with open('data.csv', 'w', encoding='utf-8') as f:
        for row in data:
            f.write(','.join(row) + '\n')
    
    print("CSV文件已创建")
    
    # 7. 使用缓冲写入
    print("\n7. 使用缓冲写入:")
    
    # 创建一个大量数据的文件
    with open('buffered_write.txt', 'w', encoding='utf-8', buffering=1024*1024) as f:  # 1MB缓冲
        for i in range(10000):
            f.write(f"这是第{i+1}行数据\n")
    
    print("带缓冲的大文件写入完成")
    
    # 8. 检查写入是否成功
    print("\n8. 检查写入是否成功:")
    
    def safe_write(filename, content, mode='w'):
        """安全写入文件,返回是否成功"""
        try:
            with open(filename, mode, encoding='utf-8') as f:
                written = f.write(content)
                print(f"成功写入 {written} 字符到 {filename}")
                return True
        except PermissionError:
            print(f"错误: 没有权限写入文件 {filename}")
            return False
        except Exception as e:
            print(f"错误: 写入文件时发生错误 - {e}")
            return False
    
    # 测试安全写入
    success = safe_write('safe_test.txt', '测试内容')
    if success:
        with open('safe_test.txt', 'r', encoding='utf-8') as f:
            print(f"验证内容: {f.read()}")
    
    # 9. 文件锁(在并发环境中)
    print("\n9. 文件锁示例:")
    import os
    
    def append_with_lock(filename, content):
        """使用文件锁进行追加写入"""
        try:
            # 打开文件并获取锁
            with open(filename, 'a', encoding='utf-8') as f:
                # 在Unix/Linux上可以使用fcntl,这里简单模拟
                f.write(f"[进程{os.getpid()}] {content}\n")
                f.flush()  # 确保立即写入
                os.fsync(f.fileno())  # 强制同步到磁盘
            return True
        except Exception as e:
            print(f"写入失败: {e}")
            return False
    
    append_with_lock('locked_file.txt', '第一条消息')
    append_with_lock('locked_file.txt', '第二条消息')
    
    with open('locked_file.txt', 'r', encoding='utf-8') as f:
        print(f"锁定文件内容:\n{f.read()}")

file_writing_methods()

二、高级文件操作

1. 文件路径操作

python 复制代码
# ==================== 文件路径操作 ====================

def file_path_operations():
    print("\n=== 文件路径操作 ===")
    
    import os
    from pathlib import Path  # Python 3.4+ 推荐使用
    
    # 1. 使用 os.path 模块
    print("1. 使用 os.path 模块:")
    
    # 当前工作目录
    cwd = os.getcwd()
    print(f"当前工作目录: {cwd}")
    
    # 路径拼接
    file_path = os.path.join(cwd, 'data', 'files', 'example.txt')
    print(f"拼接后的路径: {file_path}")
    
    # 路径分解
    dir_name = os.path.dirname(file_path)
    base_name = os.path.basename(file_path)
    print(f"目录部分: {dir_name}")
    print(f"文件名部分: {base_name}")
    
    # 获取文件名和扩展名
    file_name, file_ext = os.path.splitext(base_name)
    print(f"文件名(不含扩展名): {file_name}")
    print(f"文件扩展名: {file_ext}")
    
    # 标准化路径
    norm_path = os.path.normpath('/usr/local/../bin/./python')
    print(f"标准化路径: {norm_path}")
    
    # 绝对路径
    abs_path = os.path.abspath('example.txt')
    print(f"绝对路径: {abs_path}")
    
    # 相对路径
    rel_path = os.path.relpath('/usr/local/bin', '/usr')
    print(f"相对路径: {rel_path}")
    
    # 检查路径是否存在
    exists = os.path.exists('example.txt')
    print(f"文件是否存在: {exists}")
    
    # 2. 使用 pathlib(现代方式)
    print("\n2. 使用 pathlib(现代方式):")
    
    # 创建Path对象
    p = Path('example.txt')
    print(f"Path对象: {p}")
    print(f"绝对路径: {p.absolute()}")
    print(f"父目录: {p.parent}")
    print(f"文件名: {p.name}")
    print(f"文件名(不含扩展名): {p.stem}")
    print(f"扩展名: {p.suffix}")
    
    # 路径操作
    new_path = Path('data') / 'files' / 'example.txt'
    print(f"新路径: {new_path}")
    
    # 检查文件属性
    print(f"是否存在: {p.exists()}")
    print(f"是否是文件: {p.is_file()}")
    print(f"是否是目录: {p.is_dir()}")
    
    # 3. 遍历目录
    print("\n3. 遍历目录:")
    
    # 创建一些测试文件和目录
    test_dir = Path('test_dir')
    test_dir.mkdir(exist_ok=True)
    
    # 创建子目录和文件
    (test_dir / 'subdir1').mkdir(exist_ok=True)
    (test_dir / 'subdir2').mkdir(exist_ok=True)
    (test_dir / 'file1.txt').write_text('文件1内容')
    (test_dir / 'file2.txt').write_text('文件2内容')
    (test_dir / 'subdir1' / 'subfile.txt').write_text('子目录文件内容')
    
    # 列出目录内容
    print(f"{test_dir} 目录内容:")
    for item in test_dir.iterdir():
        if item.is_file():
            print(f"  文件: {item.name} ({item.stat().st_size} 字节)")
        elif item.is_dir():
            print(f"  目录: {item.name}")
    
    # 递归遍历
    print(f"\n递归遍历 {test_dir}:")
    for item in test_dir.rglob('*'):
        rel_path = item.relative_to(test_dir)
        print(f"  {rel_path}")
    
    # 4. 文件通配符匹配
    print("\n4. 文件通配符匹配:")
    
    # 创建一些.txt和.csv文件
    for i in range(3):
        (test_dir / f'document{i}.txt').write_text(f'文本文件{i}')
        (test_dir / f'data{i}.csv').write_text(f'CSV文件{i}')
    
    # 使用glob匹配
    print("所有.txt文件:")
    for txt_file in test_dir.glob('*.txt'):
        print(f"  {txt_file.name}")
    
    print("\n所有.csv文件:")
    for csv_file in test_dir.glob('*.csv'):
        print(f"  {csv_file.name}")
    
    print("\n递归查找所有.txt文件:")
    for txt_file in test_dir.rglob('*.txt'):
        print(f"  {txt_file.relative_to(test_dir)}")
    
    # 5. 路径操作实际应用
    print("\n5. 路径操作实际应用:")
    
    def backup_file(file_path):
        """创建文件备份"""
        path = Path(file_path)
        
        if not path.exists():
            print(f"文件 {file_path} 不存在")
            return
        
        # 生成备份文件名
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        backup_name = f"{path.stem}_backup_{timestamp}{path.suffix}"
        backup_path = path.parent / backup_name
        
        try:
            # 复制文件
            import shutil
            shutil.copy2(path, backup_path)
            print(f"已创建备份: {backup_path}")
        except Exception as e:
            print(f"备份失败: {e}")
    
    # 测试备份功能
    backup_file('example.txt')
    
    # 6. 临时文件和目录
    print("\n6. 临时文件和目录:")
    
    import tempfile
    
    # 创建临时文件
    with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as tmp:
        tmp.write("临时文件内容\n")
        tmp_name = tmp.name
        print(f"临时文件: {tmp_name}")
    
    # 读取临时文件
    with open(tmp_name, 'r') as f:
        print(f"临时文件内容: {f.read()}")
    
    # 删除临时文件
    os.unlink(tmp_name)
    print("临时文件已删除")
    
    # 创建临时目录
    with tempfile.TemporaryDirectory() as tmpdir:
        print(f"临时目录: {tmpdir}")
        temp_file = Path(tmpdir) / 'test.txt'
        temp_file.write_text('临时目录中的文件')
        print(f"临时文件内容: {temp_file.read_text()}")
    print("临时目录已自动删除")
    
    # 清理测试目录
    import shutil
    shutil.rmtree(test_dir, ignore_errors=True)

file_path_operations()

2. 上下文管理和文件操作

python 复制代码
# ==================== 上下文管理和文件操作 ====================

import time

def context_management():
    print("\n=== 上下文管理和文件操作 ===")
    
    # 1. 自定义上下文管理器类
    print("1. 自定义上下文管理器类:")
    
    class FileLogger:
        """自定义文件日志上下文管理器"""
        
        def __init__(self, filename, mode='a'):
            self.filename = filename
            self.mode = mode
            self.file = None
            self.start_time = None
        
        def __enter__(self):
            """进入上下文时调用"""
            self.start_time = time.time()
            self.file = open(self.filename, self.mode, encoding='utf-8')
            self.file.write(f"=== 日志开始于 {time.ctime(self.start_time)} ===\n")
            return self
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            """退出上下文时调用"""
            end_time = time.time()
            duration = end_time - self.start_time
            
            if exc_type is not None:
                # 如果有异常发生
                self.file.write(f"[ERROR] 异常: {exc_val}\n")
                self.file.write(f"[ERROR] 耗时: {duration:.2f}秒\n")
            else:
                # 正常结束
                self.file.write(f"=== 日志结束于 {time.ctime(end_time)} ===\n")
                self.file.write(f"=== 总耗时: {duration:.2f}秒 ===\n")
            
            self.file.close()
            
            # 返回False表示异常需要传播,True表示已处理
            return False
        
        def log(self, message, level="INFO"):
            """记录日志消息"""
            timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
            self.file.write(f"[{timestamp}] [{level}] {message}\n")
            self.file.flush()  # 立即写入
    
    # 使用自定义上下文管理器
    try:
        with FileLogger('app.log') as logger:
            logger.log("应用程序启动")
            time.sleep(0.1)
            logger.log("处理数据...")
            # 模拟一个错误
            # raise ValueError("测试错误")
            logger.log("应用程序正常关闭")
    except Exception as e:
        print(f"捕获到异常: {e}")
    
    # 读取日志文件
    with open('app.log', 'r') as f:
        print("应用程序日志:")
        print(f.read())
    
    # 2. 使用 contextlib 创建上下文管理器
    print("\n2. 使用 contextlib 创建上下文管理器:")
    
    from contextlib import contextmanager
    
    @contextmanager
    def timed_file_operation(filename, operation='read'):
        """计时文件操作的上下文管理器"""
        start_time = time.time()
        file = None
        
        try:
            if operation == 'read':
                file = open(filename, 'r', encoding='utf-8')
                print(f"开始读取文件: {filename}")
                yield file
            elif operation == 'write':
                file = open(filename, 'w', encoding='utf-8')
                print(f"开始写入文件: {filename}")
                yield file
            else:
                raise ValueError(f"不支持的操作: {operation}")
        finally:
            if file:
                file.close()
            end_time = time.time()
            duration = end_time - start_time
            print(f"文件操作完成,耗时: {duration:.3f}秒")
    
    # 使用装饰器创建的上下文管理器
    with timed_file_operation('example.txt', 'read') as f:
        content = f.read()
        print(f"读取到 {len(content)} 字符")
    
    # 3. 多重上下文管理器
    print("\n3. 多重上下文管理器:")
    
    # 同时打开多个文件
    try:
        with open('file1.txt', 'w') as f1, open('file2.txt', 'w') as f2:
            f1.write("文件1内容\n")
            f2.write("文件2内容\n")
            print("同时写入两个文件")
    except Exception as e:
        print(f"错误: {e}")
    
    # 4. 上下文管理器的实际应用
    print("\n4. 上下文管理器的实际应用:")
    
    class DatabaseConnection:
        """模拟数据库连接的上下文管理器"""
        
        def __init__(self, db_name):
            self.db_name = db_name
            self.connected = False
        
        def __enter__(self):
            print(f"连接到数据库: {self.db_name}")
            self.connected = True
            # 模拟连接耗时
            time.sleep(0.05)
            return self
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            if self.connected:
                print(f"断开数据库连接: {self.db_name}")
                self.connected = False
            if exc_type:
                print(f"数据库操作异常: {exc_val}")
            return False
        
        def query(self, sql):
            """执行查询"""
            if not self.connected:
                raise ConnectionError("数据库未连接")
            print(f"执行查询: {sql}")
            time.sleep(0.02)
            return ["结果1", "结果2", "结果3"]
    
    # 使用数据库上下文管理器
    with DatabaseConnection('my_database') as db:
        results = db.query("SELECT * FROM users")
        print(f"查询结果: {results}")
    
    # 5. 资源清理模式
    print("\n5. 资源清理模式:")
    
    class ResourceManager:
        """资源管理器,确保资源被正确清理"""
        
        def __init__(self):
            self.resources = []
        
        def add_resource(self, resource, cleanup_func):
            """添加资源及其清理函数"""
            self.resources.append((resource, cleanup_func))
            return resource
        
        def __enter__(self):
            return self
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            # 逆序清理所有资源
            for resource, cleanup_func in reversed(self.resources):
                try:
                    cleanup_func(resource)
                    print(f"已清理资源: {resource}")
                except Exception as e:
                    print(f"清理资源时出错: {e}")
            return False
    
    # 使用资源管理器
    with ResourceManager() as rm:
        # 创建文件资源
        file1 = rm.add_resource(open('temp1.txt', 'w'), lambda f: f.close())
        file1.write("临时文件1\n")
        
        file2 = rm.add_resource(open('temp2.txt', 'w'), lambda f: f.close())
        file2.write("临时文件2\n")
        
        # 模拟其他资源
        import socket
        sock = rm.add_resource(socket.socket(), lambda s: s.close())
        print("资源已添加")
    
    print("所有资源已清理")

context_management()

3. 文件编码和格式处理

python 复制代码
# ==================== 文件编码和格式处理 ====================

def file_encoding_handling():
    print("\n=== 文件编码和格式处理 ===")
    
    # 1. 不同编码的文件操作
    print("1. 不同编码的文件操作:")
    
    test_content = "Hello, 世界! 🌍\n这是一条测试消息。\n"
    
    # 使用不同编码写入文件
    encodings = ['utf-8', 'utf-16', 'gbk', 'latin-1', 'ascii']
    
    for encoding in encodings:
        try:
            filename = f'test_{encoding}.txt'
            with open(filename, 'w', encoding=encoding) as f:
                f.write(test_content)
            print(f"使用 {encoding} 编码写入成功")
            
            # 读取验证
            with open(filename, 'r', encoding=encoding) as f:
                content = f.read()
                print(f"  {encoding} 读取: {content[:20]}...")
        except UnicodeEncodeError as e:
            print(f"  {encoding} 编码错误: {e}")
        except Exception as e:
            print(f"  {encoding} 其他错误: {e}")
    
    # 2. 自动检测文件编码
    print("\n2. 自动检测文件编码:")
    
    import chardet  # 需要安装: pip install chardet
    
    def detect_encoding(filename):
        """检测文件编码"""
        try:
            with open(filename, 'rb') as f:
                raw_data = f.read()
                result = chardet.detect(raw_data)
                return result['encoding'], result['confidence']
        except Exception as e:
            return None, 0
    
    # 测试编码检测
    test_file = 'test_utf-8.txt'
    encoding, confidence = detect_encoding(test_file)
    print(f"文件 {test_file} 编码: {encoding} (置信度: {confidence:.2%})")
    
    # 3. 处理未知编码的文件
    print("\n3. 处理未知编码的文件:")
    
    def read_file_with_fallback(filename):
        """尝试多种编码读取文件"""
        encodings_to_try = ['utf-8', 'gbk', 'gb2312', 'big5', 'latin-1']
        
        for encoding in encodings_to_try:
            try:
                with open(filename, 'r', encoding=encoding) as f:
                    return f.read(), encoding
            except UnicodeDecodeError:
                continue
            except Exception as e:
                print(f"使用 {encoding} 读取时出错: {e}")
                continue
        
        # 如果所有编码都失败,尝试二进制读取
        with open(filename, 'rb') as f:
            return f.read(), 'binary'
    
    content, used_encoding = read_file_with_fallback(test_file)
    print(f"使用编码 {used_encoding} 成功读取文件")
    print(f"内容预览: {content[:50]}...")
    
    # 4. BOM(字节顺序标记)处理
    print("\n4. BOM(字节顺序标记)处理:")
    
    # 写入带BOM的UTF-8文件
    bom_content = '\ufeff' + "带BOM的UTF-8文件内容\n"
    with open('with_bom.txt', 'w', encoding='utf-8-sig') as f:
        f.write(bom_content)
    
    # 读取带BOM的文件
    with open('with_bom.txt', 'r', encoding='utf-8-sig') as f:
        content = f.read()
        print(f"读取带BOM文件: {repr(content[:20])}...")
    
    # 5. 行结束符处理
    print("\n5. 行结束符处理:")
    
    # 不同平台的换行符
    unix_content = "Unix/Linux换行\n第二行\n"
    windows_content = "Windows换行\r\n第二行\r\n"
    mac_content = "旧Mac换行\r第二行\r"
    
    # 写入不同换行符的文件
    with open('unix.txt', 'w', newline='\n') as f:
        f.write(unix_content)
    
    with open('windows.txt', 'w', newline='\r\n') as f:
        f.write(windows_content)
    
    # 读取时统一处理换行符
    with open('unix.txt', 'r', newline='') as f:
        lines = f.readlines()
        print(f"Unix文件行数: {len(lines)}")
    
    with open('windows.txt', 'r', newline='') as f:
        lines = f.readlines()
        print(f"Windows文件行数: {len(lines)}")
    
    # 6. 二进制和文本模式转换
    print("\n6. 二进制和文本模式转换:")
    
    # 文本转二进制
    text_data = "Hello, World! 你好,世界!"
    binary_data = text_data.encode('utf-8')
    
    with open('text_to_binary.bin', 'wb') as f:
        f.write(binary_data)
    
    # 二进制转文本
    with open('text_to_binary.bin', 'rb') as f:
        loaded_binary = f.read()
        loaded_text = loaded_binary.decode('utf-8')
        print(f"二进制文件解码为文本: {loaded_text}")
    
    # 7. 处理混合编码文件
    print("\n7. 处理混合编码文件(如日志文件):")
    
    def read_log_file_safely(filename):
        """安全读取可能包含混合编码的日志文件"""
        result_lines = []
        
        with open(filename, 'rb') as f:
            for line_num, line_bytes in enumerate(f, 1):
                try:
                    # 尝试UTF-8解码
                    line = line_bytes.decode('utf-8').rstrip('\n\r')
                    result_lines.append(line)
                except UnicodeDecodeError:
                    try:
                        # 尝试其他编码
                        line = line_bytes.decode('latin-1').rstrip('\n\r')
                        result_lines.append(f"[编码问题行{line_num}] {line}")
                    except:
                        # 如果所有编码都失败,使用替代字符
                        result_lines.append(f"[二进制行{line_num}] <无法解码>")
        
        return result_lines
    
    # 创建混合编码的测试文件
    mixed_content = b"正常UTF-8行\n" + "包含中文的行\n".encode('utf-8') + b"Invalid \x80\x81 bytes\n"
    
    with open('mixed_encoding.log', 'wb') as f:
        f.write(mixed_content)
    
    lines = read_log_file_safely('mixed_encoding.log')
    print("混合编码文件内容:")
    for line in lines:
        print(f"  {line}")
    
    # 8. CSV文件编码处理
    print("\n8. CSV文件编码处理:")
    
    import csv
    
    # 创建包含中文的CSV数据
    csv_data = [
        ['姓名', '年龄', '城市'],
        ['张三', '25', '北京'],
        ['李四', '30', '上海'],
        ['王五', '28', '广州']
    ]
    
    # 使用UTF-8-BOM写入CSV(Excel兼容)
    with open('data_utf8_bom.csv', 'w', encoding='utf-8-sig', newline='') as f:
        writer = csv.writer(f)
        writer.writerows(csv_data)
    
    # 读取CSV文件
    with open('data_utf8_bom.csv', 'r', encoding='utf-8-sig') as f:
        reader = csv.reader(f)
        print("CSV文件内容:")
        for row in reader:
            print(f"  {row}")
    
    # 9. JSON文件编码
    print("\n9. JSON文件编码:")
    
    import json
    
    # 创建包含中文的JSON数据
    json_data = {
        "name": "张三",
        "age": 25,
        "city": "北京",
        "languages": ["Python", "JavaScript", "中文"]
    }
    
    # 写入JSON文件(ensure_ascii=False保留中文)
    with open('data.json', 'w', encoding='utf-8') as f:
        json.dump(json_data, f, ensure_ascii=False, indent=2)
    
    # 读取JSON文件
    with open('data.json', 'r', encoding='utf-8') as f:
        loaded_data = json.load(f)
        print(f"JSON数据: {loaded_data}")
    
    # 10. 处理大文件的编码问题
    print("\n10. 处理大文件的编码问题:")
    
    def process_large_encoded_file(filename, encoding='utf-8', chunk_size=1024):
        """分块处理大编码文件"""
        print(f"处理大文件 {filename},编码: {encoding}")
        
        with open(filename, 'r', encoding=encoding) as f:
            buffer = ''
            chunk_count = 0
            char_count = 0
            
            while True:
                chunk = f.read(chunk_size)
                if not chunk:
                    break
                
                chunk_count += 1
                char_count += len(chunk)
                buffer += chunk
                
                # 按行处理缓冲区
                while '\n' in buffer:
                    line, buffer = buffer.split('\n', 1)
                    if chunk_count <= 2:  # 只显示前几行
                        print(f"  行: {line[:50]}...")
            
            print(f"  总共处理 {chunk_count} 块,{char_count} 字符")
    
    # 创建一个大文件测试
    with open('large_encoded.txt', 'w', encoding='utf-8') as f:
        for i in range(1000):
            f.write(f"第{i+1}行: 这是一些测试数据,包含中文和特殊字符。\n")
    
    process_large_encoded_file('large_encoded.txt')

file_encoding_handling()

三、实际应用示例

1. 日志文件分析器

python 复制代码
# ==================== 日志文件分析器 ====================

def log_file_analyzer():
    print("\n=== 日志文件分析器 ===")
    
    # 创建模拟日志文件
    log_content = """2024-01-15 10:15:23 INFO 应用程序启动
2024-01-15 10:15:25 INFO 用户登录成功: user123
2024-01-15 10:16:10 WARNING 磁盘空间不足: 85% used
2024-01-15 10:16:30 ERROR 数据库连接失败
2024-01-15 10:17:05 INFO 尝试重新连接数据库
2024-01-15 10:17:10 INFO 数据库连接恢复
2024-01-15 10:18:45 WARNING 内存使用率: 78%
2024-01-15 10:20:00 INFO 用户登出: user123
2024-01-15 10:20:10 ERROR 文件保存失败: permission denied
2024-01-15 10:20:30 INFO 应用程序关闭
"""
    
    with open('app_server.log', 'w') as f:
        f.write(log_content)
    
    # 日志分析类
    class LogAnalyzer:
        def __init__(self, log_file):
            self.log_file = log_file
            self.stats = {
                'total_lines': 0,
                'info': 0,
                'warning': 0,
                'error': 0,
                'by_hour': {},
                'messages': []
            }
        
        def analyze(self):
            """分析日志文件"""
            try:
                with open(self.log_file, 'r') as f:
                    for line in f:
                        self._process_line(line.strip())
                return True
            except FileNotFoundError:
                print(f"错误: 日志文件 {self.log_file} 不存在")
                return False
            except Exception as e:
                print(f"错误: 分析日志时出错 - {e}")
                return False
        
        def _process_line(self, line):
            """处理单行日志"""
            if not line:
                return
            
            self.stats['total_lines'] += 1
            self.stats['messages'].append(line)
            
            # 解析日志级别
            if 'INFO' in line:
                self.stats['info'] += 1
                level = 'INFO'
            elif 'WARNING' in line:
                self.stats['warning'] += 1
                level = 'WARNING'
            elif 'ERROR' in line:
                self.stats['error'] += 1
                level = 'ERROR'
            else:
                level = 'UNKNOWN'
            
            # 按小时统计
            try:
                # 提取时间部分
                time_part = line.split()[1]  # 获取时间部分 "10:15:23"
                hour = time_part.split(':')[0]  # 获取小时 "10"
                
                if hour not in self.stats['by_hour']:
                    self.stats['by_hour'][hour] = {'INFO': 0, 'WARNING': 0, 'ERROR': 0}
                
                self.stats['by_hour'][hour][level] += 1
            except IndexError:
                pass
        
        def print_report(self):
            """打印分析报告"""
            print(f"\n日志分析报告: {self.log_file}")
            print("=" * 50)
            
            print(f"总计日志行数: {self.stats['total_lines']}")
            print(f"INFO 级别: {self.stats['info']}")
            print(f"WARNING 级别: {self.stats['warning']}")
            print(f"ERROR 级别: {self.stats['error']}")
            
            # 按小时统计
            print("\n按小时统计:")
            for hour in sorted(self.stats['by_hour'].keys()):
                counts = self.stats['by_hour'][hour]
                total = sum(counts.values())
                print(f"  小时 {hour}:00 - 总计 {total} 条")
                for level in ['INFO', 'WARNING', 'ERROR']:
                    if counts.get(level, 0) > 0:
                        print(f"    {level}: {counts[level]}")
            
            # 错误摘要
            print("\n错误摘要:")
            error_lines = [msg for msg in self.stats['messages'] if 'ERROR' in msg]
            for i, error in enumerate(error_lines[:3], 1):  # 显示前3个错误
                print(f"  错误{i}: {error}")
            
            if len(error_lines) > 3:
                print(f"  还有 {len(error_lines) - 3} 个错误...")
            
            # 建议
            print("\n分析建议:")
            if self.stats['error'] > 5:
                print("  ⚠️  错误数量较多,建议检查系统状态")
            if self.stats['warning'] > 10:
                print("  ⚠️  警告数量较多,建议进行系统优化")
            if self.stats['info'] < self.stats['total_lines'] * 0.5:
                print("  ℹ️  正常日志比例较低,可能需要调整日志级别")
            
            # 保存报告到文件
            self._save_report()
        
        def _save_report(self):
            """保存分析报告到文件"""
            report_file = f"{self.log_file}_analysis.txt"
            with open(report_file, 'w') as f:
                f.write(f"日志分析报告: {self.log_file}\n")
                f.write(f"生成时间: {time.ctime()}\n")
                f.write("=" * 50 + "\n")
                f.write(f"总计日志行数: {self.stats['total_lines']}\n")
                f.write(f"INFO 级别: {self.stats['info']}\n")
                f.write(f"WARNING 级别: {self.stats['warning']}\n")
                f.write(f"ERROR 级别: {self.stats['error']}\n")
            
            print(f"\n详细报告已保存到: {report_file}")
    
    # 使用日志分析器
    analyzer = LogAnalyzer('app_server.log')
    if analyzer.analyze():
        analyzer.print_report()
    
    # 实时日志监控(简化版)
    print("\n=== 实时日志监控(简化版) ===")
    
    def tail_log_file(filename, n=10):
        """模拟tail命令,显示文件最后n行"""
        try:
            with open(filename, 'r') as f:
                # 高效获取最后n行的方法
                lines = []
                buffer_size = 8192
                f.seek(0, 2)  # 移动到文件末尾
                file_size = f.tell()
                
                buffer = ''
                position = file_size
                
                while position > 0 and len(lines) < n:
                    # 计算要读取的大小
                    size_to_read = min(buffer_size, position)
                    position -= size_to_read
                    
                    # 读取数据块
                    f.seek(position)
                    chunk = f.read(size_to_read)
                    
                    # 处理缓冲区
                    buffer = chunk + buffer
                    
                    # 分割行
                    while '\n' in buffer:
                        # 从后面前进
                        pos = buffer.rfind('\n')
                        if pos != -1:
                            line = buffer[pos+1:]
                            if line.strip():
                                lines.append(line)
                            buffer = buffer[:pos]
                
                # 添加剩余的缓冲区内容
                if buffer.strip():
                    lines.append(buffer)
                
                # 反转行顺序
                lines.reverse()
                
                print(f"最后 {min(n, len(lines))} 行日志:")
                for i, line in enumerate(lines[-n:], 1):
                    print(f"  {i:2d}: {line.strip()}")
                    
        except Exception as e:
            print(f"读取日志失败: {e}")
    
    tail_log_file('app_server.log', 5)

log_file_analyzer()

2. 配置文件管理器

python 复制代码
# ==================== 配置文件管理器 ====================

def config_file_manager():
    print("\n=== 配置文件管理器 ===")
    
    import json
    import configparser
    import yaml  # 需要安装: pip install pyyaml
    
    # 1. INI配置文件处理
    print("1. INI配置文件处理:")
    
    # 创建configparser对象
    config = configparser.ConfigParser()
    
    # 添加配置节和选项
    config['DATABASE'] = {
        'host': 'localhost',
        'port': '5432',
        'username': 'admin',
        'password': 'secret123',
        'database': 'mydb'
    }
    
    config['APPLICATION'] = {
        'debug': 'true',
        'log_level': 'INFO',
        'max_connections': '100',
        'timeout': '30'
    }
    
    config['PATHS'] = {
        'data_dir': '/var/data',
        'log_dir': '/var/logs',
        'cache_dir': '/tmp/cache'
    }
    
    # 写入INI文件
    with open('config.ini', 'w') as f:
        config.write(f)
    
    print("INI配置文件已创建: config.ini")
    
    # 读取INI文件
    config_read = configparser.ConfigParser()
    config_read.read('config.ini')
    
    print("\n读取的配置:")
    for section in config_read.sections():
        print(f"\n[{section}]")
        for key, value in config_read.items(section):
            print(f"  {key} = {value}")
    
    # 获取特定值
    db_host = config_read.get('DATABASE', 'host')
    debug_mode = config_read.getboolean('APPLICATION', 'debug')
    max_conn = config_read.getint('APPLICATION', 'max_connections')
    
    print(f"\n特定配置值:")
    print(f"  数据库主机: {db_host}")
    print(f"  调试模式: {debug_mode}")
    print(f"  最大连接数: {max_conn}")
    
    # 2. JSON配置文件处理
    print("\n2. JSON配置文件处理:")
    
    json_config = {
        "database": {
            "host": "localhost",
            "port": 5432,
            "credentials": {
                "username": "admin",
                "password": "secret123"
            },
            "connections": {
                "max": 100,
                "timeout": 30
            }
        },
        "application": {
            "name": "MyApp",
            "version": "1.0.0",
            "debug": True,
            "settings": {
                "log_level": "INFO",
                "cache_enabled": True,
                "cache_size": 1000
            }
        },
        "features": ["auth", "api", "dashboard", "reports"]
    }
    
    # 写入JSON文件
    with open('config.json', 'w', encoding='utf-8') as f:
        json.dump(json_config, f, indent=2, ensure_ascii=False)
    
    print("JSON配置文件已创建: config.json")
    
    # 读取JSON文件
    with open('config.json', 'r', encoding='utf-8') as f:
        loaded_json_config = json.load(f)
    
    print(f"\n应用名称: {loaded_json_config['application']['name']}")
    print(f"版本: {loaded_json_config['application']['version']}")
    print(f"功能列表: {', '.join(loaded_json_config['features'])}")
    
    # 3. YAML配置文件处理
    print("\n3. YAML配置文件处理:")
    
    yaml_config = """
# 应用配置
application:
  name: "MyApp"
  version: "1.0.0"
  debug: true
  port: 8080
  
# 数据库配置
database:
  primary:
    host: "db1.example.com"
    port: 5432
    database: "production"
  
  replica:
    host: "db2.example.com"
    port: 5432
    database: "replica"

# 特性开关
features:
  - name: "authentication"
    enabled: true
    
  - name: "analytics"
    enabled: false
    
  - name: "notifications"
    enabled: true

# 服务端点
endpoints:
  api: "/api/v1"
  docs: "/docs"
  health: "/health"
"""
    
    # 写入YAML文件
    with open('config.yaml', 'w') as f:
        f.write(yaml_config)
    
    print("YAML配置文件已创建: config.yaml")
    
    # 读取YAML文件
    try:
        with open('config.yaml', 'r') as f:
            loaded_yaml = yaml.safe_load(f)
        
        print(f"\n应用端口: {loaded_yaml['application']['port']}")
        print(f"主数据库: {loaded_yaml['database']['primary']['host']}")
        print(f"启用的特性:")
        for feature in loaded_yaml['features']:
            if feature['enabled']:
                print(f"  - {feature['name']}")
    except ImportError:
        print("注意: 需要安装pyyaml库才能读取YAML文件")
    
    # 4. 环境变量配置文件
    print("\n4. 环境变量配置文件 (.env):")
    
    env_content = """# 数据库配置
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mydb
DB_USER=admin
DB_PASSWORD=secret123

# 应用配置
APP_DEBUG=true
APP_PORT=8080
APP_SECRET_KEY=my-secret-key

# 第三方API
API_KEY=abcdef123456
API_SECRET=xyz789

# 路径配置
LOG_LEVEL=INFO
LOG_FILE=/var/log/app.log
"""
    
    with open('.env', 'w') as f:
        f.write(env_content)
    
    print("环境变量文件已创建: .env")
    
    # 简单的.env文件解析器
    def parse_env_file(filename):
        """解析.env文件"""
        config = {}
        
        try:
            with open(filename, 'r') as f:
                for line_num, line in enumerate(f, 1):
                    line = line.strip()
                    
                    # 跳过空行和注释
                    if not line or line.startswith('#'):
                        continue
                    
                    # 解析键值对
                    if '=' in line:
                        key, value = line.split('=', 1)
                        config[key.strip()] = value.strip()
                    else:
                        print(f"警告: 第{line_num}行格式错误: {line}")
        
        except FileNotFoundError:
            print(f"错误: 文件 {filename} 不存在")
        
        return config
    
    env_config = parse_env_file('.env')
    print(f"\n解析的环境变量数量: {len(env_config)}")
    print(f"数据库主机: {env_config.get('DB_HOST')}")
    print(f"应用端口: {env_config.get('APP_PORT')}")
    
    # 5. 配置管理器类
    print("\n5. 配置管理器类:")
    
    class ConfigManager:
        """统一的配置管理器"""
        
        def __init__(self):
            self.config = {}
            self.config_files = {}
        
        def load_config(self, filename):
            """加载配置文件"""
            import os
            
            if not os.path.exists(filename):
                print(f"错误: 配置文件不存在 - {filename}")
                return False
            
            ext = os.path.splitext(filename)[1].lower()
            
            try:
                if ext == '.ini':
                    self._load_ini(filename)
                elif ext == '.json':
                    self._load_json(filename)
                elif ext in ['.yaml', '.yml']:
                    self._load_yaml(filename)
                elif ext == '.env':
                    self._load_env(filename)
                else:
                    print(f"错误: 不支持的文件格式 - {ext}")
                    return False
                
                self.config_files[filename] = ext
                print(f"成功加载配置文件: {filename}")
                return True
                
            except Exception as e:
                print(f"错误: 加载配置文件失败 - {e}")
                return False
        
        def _load_ini(self, filename):
            """加载INI文件"""
            parser = configparser.ConfigParser()
            parser.read(filename)
            
            for section in parser.sections():
                self.config[section] = {}
                for key, value in parser.items(section):
                    # 尝试转换类型
                    if value.lower() in ('true', 'false'):
                        self.config[section][key] = value.lower() == 'true'
                    elif value.isdigit():
                        self.config[section][key] = int(value)
                    else:
                        try:
                            self.config[section][key] = float(value)
                        except ValueError:
                            self.config[section][key] = value
        
        def _load_json(self, filename):
            """加载JSON文件"""
            with open(filename, 'r', encoding='utf-8') as f:
                self.config.update(json.load(f))
        
        def _load_yaml(self, filename):
            """加载YAML文件"""
            try:
                import yaml
                with open(filename, 'r') as f:
                    self.config.update(yaml.safe_load(f))
            except ImportError:
                print("错误: 需要安装pyyaml库才能读取YAML文件")
                raise
        
        def _load_env(self, filename):
            """加载.env文件"""
            env_config = parse_env_file(filename)
            self.config.update(env_config)
        
        def get(self, key, default=None):
            """获取配置值"""
            # 支持点分隔的键路径,如 'database.host'
            keys = key.split('.')
            value = self.config
            
            for k in keys:
                if isinstance(value, dict) and k in value:
                    value = value[k]
                else:
                    return default
            
            return value
        
        def set(self, key, value):
            """设置配置值"""
            keys = key.split('.')
            config_ref = self.config
            
            # 导航到嵌套字典
            for k in keys[:-1]:
                if k not in config_ref or not isinstance(config_ref[k], dict):
                    config_ref[k] = {}
                config_ref = config_ref[k]
            
            config_ref[keys[-1]] = value
        
        def save(self, filename=None, format=None):
            """保存配置到文件"""
            if not filename and not self.config_files:
                print("错误: 没有指定文件名且没有已加载的配置文件")
                return False
            
            if filename:
                target_file = filename
                target_format = format or os.path.splitext(filename)[1].lower()
            else:
                # 保存到第一个加载的文件
                target_file = next(iter(self.config_files))
                target_format = self.config_files[target_file]
            
            try:
                if target_format == '.ini':
                    self._save_ini(target_file)
                elif target_format == '.json':
                    self._save_json(target_file)
                elif target_format in ['.yaml', '.yml']:
                    self._save_yaml(target_file)
                elif target_format == '.env':
                    self._save_env(target_file)
                else:
                    print(f"错误: 不支持的文件格式 - {target_format}")
                    return False
                
                print(f"配置已保存到: {target_file}")
                return True
                
            except Exception as e:
                print(f"错误: 保存配置失败 - {e}")
                return False
        
        def _save_ini(self, filename):
            """保存为INI格式"""
            parser = configparser.ConfigParser()
            
            # 将嵌套字典转换为扁平结构
            for key, value in self.config.items():
                if isinstance(value, dict):
                    parser[key] = value
                else:
                    if 'DEFAULT' not in parser:
                        parser['DEFAULT'] = {}
                    parser['DEFAULT'][key] = str(value)
            
            with open(filename, 'w') as f:
                parser.write(f)
        
        def _save_json(self, filename):
            """保存为JSON格式"""
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, indent=2, ensure_ascii=False)
        
        def _save_yaml(self, filename):
            """保存为YAML格式"""
            try:
                import yaml
                with open(filename, 'w') as f:
                    yaml.dump(self.config, f, default_flow_style=False)
            except ImportError:
                print("错误: 需要安装pyyaml库才能保存YAML文件")
                raise
        
        def _save_env(self, filename):
            """保存为.env格式"""
            with open(filename, 'w') as f:
                for key, value in self.config.items():
                    if isinstance(value, (dict, list)):
                        # 跳过复杂类型
                        continue
                    f.write(f"{key}={value}\n")
        
        def print_summary(self):
            """打印配置摘要"""
            print("\n配置摘要:")
            print(f"已加载文件: {list(self.config_files.keys())}")
            print(f"配置项数量: {self._count_items(self.config)}")
            
            # 显示一些关键配置
            print("\n关键配置项:")
            for key in ['database', 'application', 'debug', 'port']:
                value = self.get(key)
                if value is not None:
                    print(f"  {key}: {value}")
        
        def _count_items(self, config_dict):
            """递归计算配置项数量"""
            count = 0
            for key, value in config_dict.items():
                if isinstance(value, dict):
                    count += self._count_items(value)
                else:
                    count += 1
            return count
    
    # 使用配置管理器
    print("\n测试配置管理器:")
    manager = ConfigManager()
    
    # 加载JSON配置
    manager.load_config('config.json')
    
    # 获取配置值
    app_name = manager.get('application.name')
    db_port = manager.get('database.port')
    
    print(f"应用名称: {app_name}")
    print(f"数据库端口: {db_port}")
    
    # 设置新配置
    manager.set('application.version', '1.1.0')
    manager.set('new_feature.enabled', True)
    
    # 保存配置
    manager.save('config_updated.json')
    
    # 打印摘要
    manager.print_summary()

config_file_manager()

3. 文件备份和同步工具

python 复制代码
# ==================== 文件备份和同步工具 ====================

def file_backup_sync():
    print("\n=== 文件备份和同步工具 ===")
    
    import os
    import shutil
    import hashlib
    import time
    from pathlib import Path
    
    # 1. 简单文件备份
    print("1. 简单文件备份:")
    
    def simple_backup(source_file, backup_dir='backups'):
        """创建文件的简单备份"""
        
        # 确保源文件存在
        if not os.path.exists(source_file):
            print(f"错误: 源文件不存在 - {source_file}")
            return False
        
        # 创建备份目录
        os.makedirs(backup_dir, exist_ok=True)
        
        # 生成备份文件名(带时间戳)
        source_path = Path(source_file)
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        backup_name = f"{source_path.stem}_backup_{timestamp}{source_path.suffix}"
        backup_path = Path(backup_dir) / backup_name
        
        try:
            # 复制文件
            shutil.copy2(source_file, backup_path)
            print(f"已创建备份: {backup_path}")
            
            # 验证备份
            if os.path.getsize(source_file) == os.path.getsize(backup_path):
                print("备份验证成功: 文件大小一致")
                return True
            else:
                print("警告: 备份文件大小不一致")
                return False
                
        except Exception as e:
            print(f"备份失败: {e}")
            return False
    
    # 测试简单备份
    with open('important_data.txt', 'w') as f:
        f.write("这是重要数据\n需要备份的内容\n")
    
    simple_backup('important_data.txt')
    
    # 2. 增量备份(基于文件哈希)
    print("\n2. 增量备份(基于文件哈希):")
    
    def calculate_file_hash(filename, algorithm='md5'):
        """计算文件的哈希值"""
        hash_func = hashlib.new(algorithm)
        
        try:
            with open(filename, 'rb') as f:
                # 分块读取大文件
                for chunk in iter(lambda: f.read(4096), b''):
                    hash_func.update(chunk)
            return hash_func.hexdigest()
        except Exception as e:
            print(f"计算哈希失败: {e}")
            return None
    
    def incremental_backup(source_file, backup_dir='incremental_backups', max_backups=5):
        """创建增量备份"""
        
        if not os.path.exists(source_file):
            print(f"错误: 源文件不存在 - {source_file}")
            return None
        
        # 计算当前文件的哈希
        current_hash = calculate_file_hash(source_file)
        if not current_hash:
            return None
        
        # 检查是否需要备份
        backup_dir_path = Path(backup_dir)
        backup_dir_path.mkdir(exist_ok=True)
        
        # 查找已有的备份
        existing_backups = []
        for backup_file in backup_dir_path.glob(f"*{Path(source_file).suffix}"):
            if 'backup_' in backup_file.name:
                existing_backups.append(backup_file)
        
        # 检查是否有相同哈希的备份
        for backup in existing_backups:
            if calculate_file_hash(backup) == current_hash:
                print(f"文件未更改,跳过备份 (哈希: {current_hash[:8]}...)")
                return backup
        
        # 创建新备份
        source_path = Path(source_file)
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        backup_name = f"{source_path.stem}_backup_{timestamp}_{current_hash[:8]}{source_path.suffix}"
        backup_path = backup_dir_path / backup_name
        
        try:
            shutil.copy2(source_file, backup_path)
            print(f"创建增量备份: {backup_path.name}")
            
            # 清理旧备份(保留最新的max_backups个)
            existing_backups.sort(key=os.path.getmtime, reverse=True)
            
            if len(existing_backups) >= max_backups:
                for old_backup in existing_backups[max_backups-1:]:
                    os.remove(old_backup)
                    print(f"删除旧备份: {old_backup.name}")
            
            return backup_path
            
        except Exception as e:
            print(f"增量备份失败: {e}")
            return None
    
    # 测试增量备份
    print("第一次备份(文件初始状态):")
    backup1 = incremental_backup('important_data.txt')
    
    # 修改文件
    with open('important_data.txt', 'a') as f:
        f.write("新增的内容\n")
    
    print("\n第二次备份(文件已修改):")
    backup2 = incremental_backup('important_data.txt')
    
    print("\n第三次备份(文件未修改):")
    backup3 = incremental_backup('important_data.txt')
    
    # 3. 目录同步
    print("\n3. 目录同步:")
    
    def sync_directories(source_dir, target_dir, dry_run=False):
        """同步两个目录(单向)"""
        
        source_path = Path(source_dir)
        target_path = Path(target_dir)
        
        if not source_path.exists():
            print(f"错误: 源目录不存在 - {source_dir}")
            return False
        
        # 创建目标目录
        target_path.mkdir(parents=True, exist_ok=True)
        
        changes = {
            'created': 0,
            'updated': 0,
            'deleted': 0,
            'skipped': 0
        }
        
        # 同步文件
        for source_file in source_path.rglob('*'):
            if source_file.is_file():
                # 计算相对路径
                rel_path = source_file.relative_to(source_path)
                target_file = target_path / rel_path
                
                # 确保目标目录存在
                target_file.parent.mkdir(parents=True, exist_ok=True)
                
                # 检查是否需要同步
                sync_needed = False
                
                if not target_file.exists():
                    # 目标文件不存在
                    sync_needed = True
                    action = "创建"
                else:
                    # 检查文件是否相同(大小和修改时间)
                    source_stat = source_file.stat()
                    target_stat = target_file.stat()
                    
                    if (source_stat.st_size != target_stat.st_size or 
                        source_stat.st_mtime > target_stat.st_mtime):
                        sync_needed = True
                        action = "更新"
                    else:
                        action = "跳过"
                
                # 执行同步
                if sync_needed and not dry_run:
                    try:
                        shutil.copy2(source_file, target_file)
                        if action == "创建":
                            changes['created'] += 1
                        else:
                            changes['updated'] += 1
                        print(f"[{action}] {rel_path}")
                    except Exception as e:
                        print(f"[错误] 同步 {rel_path} 失败: {e}")
                        changes['skipped'] += 1
                elif dry_run:
                    print(f"[模拟 {action}] {rel_path}")
                    if action in ["创建", "更新"]:
                        changes[action.lower() + 'd'] += 1
                else:
                    changes['skipped'] += 1
        
        # 删除目标目录中不存在于源目录的文件
        for target_file in target_path.rglob('*'):
            if target_file.is_file():
                rel_path = target_file.relative_to(target_path)
                source_file = source_path / rel_path
                
                if not source_file.exists():
                    if not dry_run:
                        try:
                            target_file.unlink()
                            changes['deleted'] += 1
                            print(f"[删除] {rel_path}")
                        except Exception as e:
                            print(f"[错误] 删除 {rel_path} 失败: {e}")
                            changes['skipped'] += 1
                    else:
                        print(f"[模拟 删除] {rel_path}")
                        changes['deleted'] += 1
        
        # 报告结果
        print(f"\n同步完成:")
        print(f"  创建: {changes['created']} 个文件")
        print(f"  更新: {changes['updated']} 个文件")
        print(f"  删除: {changes['deleted']} 个文件")
        print(f"  跳过: {changes['skipped']} 个文件")
        
        return True
    
    # 创建测试目录结构
    test_source = Path('test_source')
    test_target = Path('test_target')
    
    # 清理旧目录
    shutil.rmtree(test_source, ignore_errors=True)
    shutil.rmtree(test_target, ignore_errors=True)
    
    # 创建源目录结构
    (test_source / 'docs').mkdir(parents=True, exist_ok=True)
    (test_source / 'images').mkdir(parents=True, exist_ok=True)
    
    # 创建一些测试文件
    (test_source / 'file1.txt').write_text('文件1内容')
    (test_source / 'docs' / 'readme.txt').write_text('说明文档')
    (test_source / 'images' / 'icon.png').write_bytes(b'fake image data')
    
    # 创建目标目录(已有一些文件)
    test_target.mkdir(exist_ok=True)
    (test_target / 'old_file.txt').write_text('旧文件')
    
    print("执行目录同步(模拟运行):")
    sync_directories(test_source, test_target, dry_run=True)
    
    print("\n执行实际同步:")
    sync_directories(test_source, test_target, dry_run=False)
    
    # 4. 文件版本控制系统(简化版)
    print("\n4. 文件版本控制系统(简化版):")
    
    class SimpleVersionControl:
        """简单的文件版本控制"""
        
        def __init__(self, repo_dir='.simple_vcs'):
            self.repo_dir = Path(repo_dir)
            self.versions_file = self.repo_dir / 'versions.json'
            self.versions = {}
            
            # 初始化仓库
            self.repo_dir.mkdir(exist_ok=True)
            
            if self.versions_file.exists():
                try:
                    import json
                    with open(self.versions_file, 'r') as f:
                        self.versions = json.load(f)
                except:
                    self.versions = {}
        
        def add_file(self, filepath, message=""):
            """添加文件到版本控制"""
            source_path = Path(filepath)
            
            if not source_path.exists():
                print(f"错误: 文件不存在 - {filepath}")
                return False
            
            # 计算文件哈希
            file_hash = calculate_file_hash(filepath)
            if not file_hash:
                return False
            
            # 检查是否已有相同版本
            if filepath in self.versions:
                last_hash = self.versions[filepath]['versions'][-1]['hash']
                if file_hash == last_hash:
                    print(f"文件未更改,跳过版本控制: {filepath}")
                    return True
            
            # 创建版本记录
            version_info = {
                'timestamp': time.time(),
                'hash': file_hash,
                'message': message,
                'size': os.path.getsize(filepath)
            }
            
            # 保存文件版本
            version_dir = self.repo_dir / 'files' / file_hash[:2]
            version_dir.mkdir(parents=True, exist_ok=True)
            version_file = version_dir / file_hash
            
            try:
                shutil.copy2(filepath, version_file)
                
                # 更新版本记录
                if filepath not in self.versions:
                    self.versions[filepath] = {
                        'created': time.time(),
                        'versions': []
                    }
                
                self.versions[filepath]['versions'].append(version_info)
                
                # 保存版本信息
                self._save_versions()
                
                print(f"添加版本: {filepath} ({message})")
                return True
                
            except Exception as e:
                print(f"添加版本失败: {e}")
                return False
        
        def list_versions(self, filepath=None):
            """列出版本"""
            if not self.versions:
                print("版本库为空")
                return
            
            if filepath:
                if filepath in self.versions:
                    print(f"\n文件: {filepath}")
                    print(f"创建时间: {time.ctime(self.versions[filepath]['created'])}")
                    print("版本历史:")
                    for i, version in enumerate(self.versions[filepath]['versions']):
                        print(f"  [{i}] {time.ctime(version['timestamp'])} "
                              f"- {version['message']} "
                              f"(哈希: {version['hash'][:8]}..., "
                              f"大小: {version['size']}字节)")
                else:
                    print(f"文件不在版本控制中: {filepath}")
            else:
                print("\n版本库中的所有文件:")
                for filepath, info in self.versions.items():
                    version_count = len(info['versions'])
                    print(f"  {filepath}: {version_count}个版本")
        
        def restore_version(self, filepath, version_index=-1):
            """恢复文件到指定版本"""
            if filepath not in self.versions:
                print(f"错误: 文件不在版本控制中 - {filepath}")
                return False
            
            versions = self.versions[filepath]['versions']
            
            if version_index < 0:
                version_index = len(versions) + version_index
            
            if version_index < 0 or version_index >= len(versions):
                print(f"错误: 无效的版本索引 {version_index}")
                return False
            
            version_info = versions[version_index]
            version_hash = version_info['hash']
            
            # 查找版本文件
            version_file = self.repo_dir / 'files' / version_hash[:2] / version_hash
            
            if not version_file.exists():
                print(f"错误: 版本文件不存在 - {version_hash}")
                return False
            
            try:
                # 备份当前文件
                current_file = Path(filepath)
                if current_file.exists():
                    backup_file = current_file.with_suffix(current_file.suffix + '.bak')
                    shutil.copy2(current_file, backup_file)
                    print(f"已创建当前文件备份: {backup_file}")
                
                # 恢复版本
                shutil.copy2(version_file, filepath)
                print(f"已恢复文件到版本 [{version_index}] "
                      f"({time.ctime(version_info['timestamp'])})")
                return True
                
            except Exception as e:
                print(f"恢复版本失败: {e}")
                return False
        
        def _save_versions(self):
            """保存版本信息"""
            try:
                import json
                with open(self.versions_file, 'w') as f:
                    json.dump(self.versions, f, indent=2)
            except Exception as e:
                print(f"保存版本信息失败: {e}")
    
    # 测试简单版本控制
    print("测试简单版本控制系统:")
    vcs = SimpleVersionControl()
    
    # 添加文件版本
    vcs.add_file('important_data.txt', '初始版本')
    
    # 修改文件
    with open('important_data.txt', 'a') as f:
        f.write("第二次修改\n")
    vcs.add_file('important_data.txt', '第二次修改')
    
    # 再次修改
    with open('important_data.txt', 'a') as f:
        f.write("第三次修改\n")
    vcs.add_file('important_data.txt', '第三次修改')
    
    # 列出版本
    vcs.list_versions('important_data.txt')
    
    # 恢复版本
    print("\n恢复文件到第一个版本:")
    vcs.restore_version('important_data.txt', 0)
    
    # 验证恢复
    with open('important_data.txt', 'r') as f:
        print(f"恢复后的内容:\n{f.read()}")
    
    # 清理测试文件
    print("\n清理测试文件...")
    test_files = [
        'test.txt', 'example.txt', 'data.txt', 'write_test.txt', 
        'writelines_test.txt', 'append_test.txt', 'rplus_test.txt',
        'binary_write.bin', 'data.csv', 'buffered_write.txt',
        'safe_test.txt', 'locked_file.txt', 'large_data.txt',
        'test_utf-8.txt', 'test_utf-16.txt', 'test_gbk.txt',
        'test_latin-1.txt', 'test_ascii.txt', 'with_bom.txt',
        'unix.txt', 'windows.txt', 'text_to_binary.bin',
        'mixed_encoding.log', 'data_utf8_bom.csv', 'data.json',
        'large_encoded.txt', 'app_server.log', 'config.ini',
        'config.json', 'config.yaml', '.env', 'config_updated.json',
        'important_data.txt', 'app.log', 'temp1.txt', 'temp2.txt'
    ]
    
    for file in test_files:
        if os.path.exists(file):
            try:
                os.remove(file)
                print(f"删除: {file}")
            except:
                pass
    
    # 清理目录
    import shutil
    dirs_to_clean = ['backups', 'incremental_backups', '.simple_vcs']
    for dir_name in dirs_to_clean:
        if os.path.exists(dir_name):
            shutil.rmtree(dir_name)
            print(f"删除目录: {dir_name}")
    
    print("清理完成!")

file_backup_sync()

四、最佳实践和性能优化

python 复制代码
# ==================== 最佳实践和性能优化 ====================

def best_practices_and_performance():
    print("\n=== 文件操作最佳实践和性能优化 ===")
    
    import time
    import os
    
    # 1. 大文件处理策略
    print("1. 大文件处理策略:")
    
    def process_large_file_efficiently(filename, process_func):
        """高效处理大文件"""
        print(f"处理大文件: {filename}")
        start_time = time.time()
        
        try:
            with open(filename, 'r', encoding='utf-8') as f:
                # 逐行处理,避免一次性加载到内存
                line_count = 0
                for line in f:
                    process_func(line.strip())
                    line_count += 1
                    
                    # 进度提示
                    if line_count % 10000 == 0:
                        elapsed = time.time() - start_time
                        print(f"  已处理 {line_count} 行,耗时 {elapsed:.2f}秒")
            
            elapsed = time.time() - start_time
            print(f"完成! 总共处理 {line_count} 行,耗时 {elapsed:.2f}秒")
            return line_count
            
        except Exception as e:
            print(f"处理文件时出错: {e}")
            return 0
    
    # 创建测试大文件
    large_filename = 'large_test_file.txt'
    with open(large_filename, 'w', encoding='utf-8') as f:
        for i in range(50000):
            f.write(f"这是第{i+1}行数据,包含一些文本用于测试大文件处理性能。\n")
    
    # 定义处理函数
    def count_words(line):
        return len(line.split())
    
    total_words = 0
    
    def process_line(line):
        global total_words
        total_words += count_words(line)
    
    print("逐行处理大文件:")
    lines_processed = process_large_file_efficiently(large_filename, process_line)
    print(f"总单词数: {total_words}")
    
    # 2. 内存映射文件
    print("\n2. 内存映射文件:")
    
    import mmap
    
    def memory_mapped_example(filename):
        """使用内存映射处理大文件"""
        print(f"使用内存映射处理: {filename}")
        
        file_size = os.path.getsize(filename)
        print(f"文件大小: {file_size:,} 字节")
        
        with open(filename, 'r+b') as f:
            # 创建内存映射
            with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mm:
                # 在内存中直接搜索
                search_bytes = b"第10000行"
                position = mm.find(search_bytes)
                
                if position != -1:
                    # 读取找到的内容
                    mm.seek(position)
                    content = mm.read(100).decode('utf-8', errors='ignore')
                    print(f"找到 '第10000行' 在位置 {position}: {content}")
                else:
                    print("未找到搜索内容")
                
                # 统计换行符数量(行数)
                newline_count = mm.count(b'\n')
                print(f"估计行数: {newline_count}")
    
    # 测试内存映射
    memory_mapped_example(large_filename)
    
    # 3. 并行文件处理
    print("\n3. 并行文件处理:")
    
    from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
    
    def parallel_file_processing(filename, num_workers=4):
        """并行处理文件的不同部分"""
        print(f"并行处理文件,使用 {num_workers} 个工作线程")
        
        file_size = os.path.getsize(filename)
        chunk_size = file_size // num_workers
        
        def process_chunk(chunk_id, start, end):
            """处理文件块"""
            local_count = 0
            with open(filename, 'r', encoding='utf-8') as f:
                f.seek(start)
                
                # 调整起始位置到行首
                if start > 0:
                    f.readline()  # 跳过可能不完整的行
                
                # 处理指定范围内的行
                while f.tell() < end:
                    line = f.readline()
                    if not line:
                        break
                    local_count += 1
            
            return chunk_id, local_count
        
        # 计算各块的起始位置
        chunks = []
        for i in range(num_workers):
            start = i * chunk_size
            end = start + chunk_size if i < num_workers - 1 else file_size
            chunks.append((i, start, end))
        
        # 并行处理
        start_time = time.time()
        total_lines = 0
        
        with ThreadPoolExecutor(max_workers=num_workers) as executor:
            futures = [executor.submit(process_chunk, *chunk) for chunk in chunks]
            
            for future in futures:
                chunk_id, count = future.result()
                total_lines += count
                print(f"  块{chunk_id}: 处理了 {count} 行")
        
        elapsed = time.time() - start_time
        print(f"并行处理完成: 总共 {total_lines} 行,耗时 {elapsed:.2f}秒")
        return total_lines
    
    # 测试并行处理
    parallel_lines = parallel_file_processing(large_filename, 4)
    
    # 4. 文件操作缓存
    print("\n4. 文件操作缓存:")
    
    import functools
    
    class FileCache:
        """文件内容缓存"""
        
        def __init__(self, max_size=10):
            self.cache = {}
            self.max_size = max_size
            self.access_order = []
        
        @functools.lru_cache(maxsize=10)
        def read_file_cached(self, filename):
            """带缓存的文件读取"""
            print(f"缓存读取: {filename}")
            with open(filename, 'r', encoding='utf-8') as f:
                return f.read()
        
        def get_file_stats(self, filename):
            """获取文件统计信息(带缓存)"""
            if filename in self.cache:
                stats, timestamp = self.cache[filename]
                
                # 检查缓存是否过期
                current_mtime = os.path.getmtime(filename)
                if current_mtime <= timestamp:
                    print(f"使用缓存: {filename}")
                    return stats
            
            # 重新计算并缓存
            print(f"计算并缓存: {filename}")
            stats = {
                'size': os.path.getsize(filename),
                'mtime': os.path.getmtime(filename),
                'lines': self._count_lines(filename)
            }
            
            self.cache[filename] = (stats, time.time())
            self.access_order.append(filename)
            
            # 清理旧缓存
            if len(self.cache) > self.max_size:
                oldest = self.access_order.pop(0)
                del self.cache[oldest]
            
            return stats
        
        def _count_lines(self, filename):
            """快速统计行数"""
            count = 0
            with open(filename, 'r', encoding='utf-8') as f:
                for _ in f:
                    count += 1
            return count
    
    # 测试文件缓存
    cache = FileCache(max_size=3)
    
    print("第一次获取统计(会计算):")
    stats1 = cache.get_file_stats(large_filename)
    print(f"  大小: {stats1['size']:,} 字节,行数: {stats1['lines']}")
    
    print("\n第二次获取统计(使用缓存):")
    stats2 = cache.get_file_stats(large_filename)
    print(f"  大小: {stats2['size']:,} 字节")
    
    # 5. 异步文件操作
    print("\n5. 异步文件操作:")
    
    import asyncio
    
    async def async_read_file(filename):
        """异步读取文件"""
        print(f"开始异步读取: {filename}")
        
        # 在单独的线程中执行阻塞IO
        loop = asyncio.get_event_loop()
        
        def read_file_sync():
            with open(filename, 'r', encoding='utf-8') as f:
                return f.read()
        
        content = await loop.run_in_executor(None, read_file_sync)
        print(f"异步读取完成: {filename} ({len(content):,} 字符)")
        return content
    
    async def async_write_file(filename, content):
        """异步写入文件"""
        print(f"开始异步写入: {filename}")
        
        loop = asyncio.get_event_loop()
        
        def write_file_sync():
            with open(filename, 'w', encoding='utf-8') as f:
                return f.write(content)
        
        written = await loop.run_in_executor(None, write_file_sync)
        print(f"异步写入完成: {filename} ({written} 字符)")
        return written
    
    async def async_file_operations():
        """异步文件操作示例"""
        print("执行异步文件操作...")
        
        # 并发执行多个文件操作
        read_task = async_read_file(large_filename)
        write_task = async_write_file('async_output.txt', '异步写入的内容\n')
        
        # 等待所有任务完成
        results = await asyncio.gather(read_task, write_task)
        print(f"异步操作完成,读取 {len(results[0]):,} 字符,写入 {results[1]} 字符")
    
    # 运行异步示例
    try:
        asyncio.run(async_file_operations())
    except RuntimeError:
        print("注意: 异步示例需要在异步环境中运行")
    
    # 6. 文件操作性能对比
    print("\n6. 文件操作性能对比:")
    
    def performance_comparison():
        """不同文件操作方式的性能对比"""
        
        test_data = 'x' * 1000000  # 1MB数据
        
        # 测试1: 普通写入
        start = time.time()
        with open('test1.txt', 'w') as f:
            f.write(test_data)
        time1 = time.time() - start
        
        # 测试2: 带缓冲的写入
        start = time.time()
        with open('test2.txt', 'w', buffering=1024*1024) as f:  # 1MB缓冲
            f.write(test_data)
        time2 = time.time() - start
        
        # 测试3: 二进制写入
        start = time.time()
        with open('test3.txt', 'wb') as f:
            f.write(test_data.encode('utf-8'))
        time3 = time.time() - start
        
        # 测试4: 分块写入
        start = time.time()
        chunk_size = 8192
        with open('test4.txt', 'w') as f:
            for i in range(0, len(test_data), chunk_size):
                f.write(test_data[i:i+chunk_size])
        time4 = time.time() - start
        
        print("写入性能对比 (1MB数据):")
        print(f"  普通写入: {time1:.4f}秒")
        print(f"  带缓冲写入: {time2:.4f}秒")
        print(f"  二进制写入: {time3:.4f}秒")
        print(f"  分块写入: {time4:.4f}秒")
        
        # 清理测试文件
        for i in range(1, 5):
            try:
                os.remove(f'test{i}.txt')
            except:
                pass
    
    performance_comparison()
    
    # 7. 安全文件操作
    print("\n7. 安全文件操作:")
    
    def secure_file_operations():
        """安全文件操作最佳实践"""
        
        import tempfile
        
        # 1. 使用临时文件处理敏感数据
        with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp:
            tmp.write("敏感数据\n")
            tmp_path = tmp.name
        
        try:
            # 处理临时文件
            with open(tmp_path, 'r') as f:
                content = f.read()
                print(f"处理敏感数据: {content[:20]}...")
        finally:
            # 确保删除临时文件
            os.unlink(tmp_path)
            print("临时文件已安全删除")
        
        # 2. 安全的文件权限
        secure_file = 'secure_data.txt'
        
        # 创建文件时设置权限
        with open(secure_file, 'w') as f:
            f.write("敏感信息\n")
        
        # 设置文件权限(仅所有者可读写)
        os.chmod(secure_file, 0o600)
        
        # 检查权限
        stat_info = os.stat(secure_file)
        print(f"文件权限: {oct(stat_info.st_mode)[-3:]}")
        
        # 3. 安全删除文件(覆盖数据)
        def secure_delete(filename, passes=3):
            """安全删除文件,覆盖数据"""
            try:
                file_size = os.path.getsize(filename)
                
                with open(filename, 'rb+') as f:
                    for pass_num in range(passes):
                        # 写入随机数据
                        f.seek(0)
                        f.write(os.urandom(file_size))
                        f.flush()
                        os.fsync(f.fileno())
                
                # 重命名文件
                temp_name = filename + '.deleted'
                os.rename(filename, temp_name)
                
                # 删除文件
                os.unlink(temp_name)
                
                print(f"文件已安全删除: {filename}")
                return True
                
            except Exception as e:
                print(f"安全删除失败: {e}")
                return False
        
        # 测试安全删除
        secure_delete(secure_file)
    
    secure_file_operations()
    
    # 清理大文件
    os.remove(large_filename)
    print(f"\n已清理测试文件: {large_filename}")

best_practices_and_performance()

总结

Python文件操作要点:

  1. 打开模式

    • 'r': 只读
    • 'w': 写入(覆盖)
    • 'a': 追加
    • 'x': 创建新文件
    • 'b': 二进制模式
    • '+': 读写模式
  2. 推荐实践

    • 始终使用with语句确保文件正确关闭
    • 指定明确的编码(如utf-8
    • 处理文件操作异常
    • 对大文件使用迭代而不是一次性读取
  3. 性能优化

    • 对大文件使用逐行或分块处理
    • 考虑使用内存映射(mmap)处理超大文件
    • 对频繁读取的文件使用缓存
    • 考虑异步或并行处理
  4. 安全性

    • 验证文件路径,防止路径遍历攻击
    • 对敏感数据使用临时文件
    • 设置适当的文件权限
    • 安全删除敏感文件
  5. 现代特性

    • 使用pathlib进行路径操作(Python 3.4+)
    • 使用os.scandir()进行高效目录遍历
    • 考虑使用异步IO处理大量文件操作

掌握这些文件操作技术可以帮助你编写更高效、更安全、更可靠的Python程序。



现代C++的文件操作核心是基于流的<fstream>库,它提供了类似控制台I/O(cin/cout)的接口来处理文件。为了方便你快速理解其与Python的差异,我先用一个表格进行对比:

特性 Python C++ (现代)
核心机制 基于文件对象 (open函数) 基于流对象 (ifstream, ofstream, fstream)
打开方式 模式字符串 (如 "r", "wb") 模式标志组合 (如 `std::ios::in
资源管理 依赖 with 语句或手动 close() RAII (推荐) :对象析构时自动关闭;也可手动 close()
读取接口 read(), readline(), 迭代 流提取符 (>>)getline()read() (二进制)
写入接口 write(), writelines() 流插入符 (<<)write() (二进制)
路径处理 os.path, pathlib (Python 3.4+) std::filesystem (C++17)
错误处理 抛出异常 (如 FileNotFoundError) 主要检查流状态 (如 !ifile),也可设置异常模式
现代特性 - C++17 std::filesystemC++20 std::format 格式化

📝 核心操作与代码示例

1. 基础文本文件读写

这是最常用的场景,使用流操作符 <<>> 就像使用 coutcin

cpp 复制代码
#include <iostream>
#include <fstream>
#include <string>

int main() {
    // 写入文件 (输出文件流)
    std::ofstream out_file("example.txt"); // 默认模式为写入并截断
    if (!out_file) { // 检查文件是否成功打开
        std::cerr << "打开文件失败 (写入)!" << std::endl;
        return 1;
    }
    out_file << "Hello, File!\n"; // 像使用cout一样写入
    out_file << 42 << " " << 3.14 << std::endl;
    // 文件会在out_file析构时自动关闭

    // 读取文件 (输入文件流)
    std::ifstream in_file("example.txt");
    if (!in_file.is_open()) { // 另一种检查方式
        std::cerr << "打开文件失败 (读取)!" << std::endl;
        return 1;
    }
    std::string line;
    int num;
    double pi;

    std::getline(in_file, line); // 读取一整行
    in_file >> num >> pi; // 按空格分隔读取数据

    std::cout << "行内容: " << line << std::endl;
    std::cout << "数字: " << num << ", PI: " << pi << std::endl;

    return 0;
}
2. 二进制文件读写

处理图像、结构体等非文本数据时,必须使用二进制模式(std::ios::binary)和 read/write 方法。

cpp 复制代码
#include <iostream>
#include <fstream>
#include <cstring> // for strcpy (仅为示例,实践中可用std::string或std::array)

struct Person {
    char name[50];
    int age;
};

int main() {
    Person people[2] = {{"Alice", 30}, {"Bob", 25}};

    // 写入二进制文件
    std::ofstream b_out("data.bin", std::ios::binary); // 必须指定二进制模式
    if (b_out) {
        // write参数为(char*)和字节数
        b_out.write(reinterpret_cast<const char*>(people), 2 * sizeof(Person));
        // 无需显式关闭,析构函数处理
    }

    // 读取二进制文件
    Person loaded_people[2];
    std::ifstream b_in("data.bin", std::ios::binary);
    if (b_in) {
        b_in.read(reinterpret_cast<char*>(loaded_people), 2 * sizeof(Person));
        for (const auto& p : loaded_people) {
            std::cout << "姓名: " << p.name << ", 年龄: " << p.age << std::endl;
        }
    }
    return 0;
}
3. 文件指针与随机访问

通过 seekg(用于输入/get)和 seekp(用于输出/put)可以移动文件指针,实现随机读写。

cpp 复制代码
#include <iostream>
#include <fstream>

int main() {
    std::fstream file("random_access.txt", std::ios::in | std::ios::out | std::ios::trunc);
    file << "1234567890ABCDEFGHIJ"; // 写入测试数据

    // 将"读指针"移动到第10个字节(从0开始,即'A')
    file.seekg(10, std::ios::beg); // 从文件开始处偏移
    char ch;
    file.get(ch); // 读取一个字符
    std::cout << "位置10的字符: " << ch << std::endl; // 输出: A

    // 获取当前"写指针"位置(在末尾)
    std::streampos write_pos = file.tellp();
    std::cout << "当前写指针位置: " << write_pos << std::endl;

    // 将"写指针"从当前位置回退5个字节
    file.seekp(-5, std::ios::cur);
    file << "OVER"; // 覆盖数据
    // 此时文件内容变为 "1234567890OVEREFGHIJ"

    return 0;
}

🚀 现代C++的增强特性

1. 使用 std::filesystem (C++17)

C++17引入的 <filesystem> 库极大简化了路径和文件系统操作。

cpp 复制代码
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem; // 别名简化

int main() {
    fs::path file_path = "data/subdir/example.txt";

    // 创建目录(包括父目录)
    fs::create_directories(file_path.parent_path());

    // 检查文件状态
    if (fs::exists(file_path)) {
        std::cout << "文件大小: " << fs::file_size(file_path) << " 字节\n";
    }

    // 遍历目录
    for (const auto& entry : fs::directory_iterator(".")) {
        std::cout << entry.path() << " - "
                  << (fs::is_directory(entry.status()) ? "目录" : "文件") << std::endl;
    }

    // 复制文件
    fs::copy_file(file_path, "backup.txt", fs::copy_options::overwrite_existing);
    return 0;
}
2. 结合 std::string_viewstd::format (C++17/20)

使用现代字符串视图和格式化工具,使代码更安全、高效。

cpp 复制代码
#include <iostream>
#include <fstream>
#include <string_view>
#include <format> // C++20

void write_log(std::string_view filename, std::string_view message, int id) {
    std::ofstream log(filename.data(), std::ios::app); // 追加模式
    if (log) {
        // C++20 格式化 (更安全、类型安全)
        log << std::format("[ID:{:03d}] {}\n", id, message);
    }
}

int main() {
    write_log("app.log", "程序启动", 1);
    write_log("app.log", "处理数据", 2);
    return 0;
}

💡 最佳实践与要点

  1. 坚持RAII原则:优先在局部作用域内声明文件流对象,利用析构函数自动关闭文件,避免资源泄漏。
  2. 务必检查打开状态 :文件打开可能因权限、路径错误等失败,在操作前使用 if (stream)is_open() 进行检查是必需的。
  3. 区分文本与二进制模式 :处理图片、结构体或跨平台需求时,务必使用 std::ios::binary 模式,否则可能发生意外的字符转换(如换行符)。
  4. 理解文件打开模式 :常用的组合有 std::ios::in | std::ios::out(读写)、std::ios::app(追加)等。
  5. 优先使用标准库 :对于路径操作,优先使用 std::filesystem 而非手动拼接字符串,它更安全且跨平台。

如果你想进一步了解如何在C++中处理特定格式的文件(如CSV或JSON),我可以为你提供更具体的代码示例和库推荐。

相关推荐
TT哇1 小时前
关闭外键约束检查
数据库·sql·oracle
卿雪1 小时前
Redis 数据持久化:RDB和 AOF 有什么区别?
java·数据库·redis·python·mysql·缓存·golang
Chasing Aurora1 小时前
Python后端开发之旅(二)
开发语言·python·语言模型·langchain·ai编程
2401_891957311 小时前
简单了解一下智能指针(C++)
开发语言·c++
archko1 小时前
用rust写了一个桌面app,就不再想用kmp了
开发语言·后端·rust
闲人编程1 小时前
微服务API网关设计模式
python·缓存·微服务·设计模式·系统安全·api·codecapsule
计算机毕设MTU77571 小时前
999+套计算机毕业设计——基于HTML5+CSS的图书馆借阅管理系统的设计与实现(含源码+部署教程+数据库)
数据库·spring boot·课程设计·借阅管理系统·图书馆
星释1 小时前
Rust 练习册 109:深入探索列表关系判断
开发语言·后端·rust
lsx2024061 小时前
Python3 实例
开发语言