引言
在编程中,数据的持久化存储是一个非常重要的概念。无论是在程序运行过程中保存用户设置、记录日志信息,还是处理大量数据,我们都需要将数据保存到文件中,以便在程序重启后仍然可以访问这些数据。
Python提供了强大而灵活的文件操作功能,支持文本文件和二进制文件的读写操作。通过内置的open()函数和文件对象的各种方法,我们可以轻松地处理各种类型的文件。
在本章中,我们将深入学习Python的文件操作机制,包括文件的打开和关闭、不同的文件模式、文本文件和二进制文件的处理、文件对象的方法、目录操作等内容。通过实际的例子,你将学会如何高效地处理各种文件操作任务。
学习目标
完成本章学习后,你将能够:
- 理解文件操作的基本概念和重要性
- 掌握open()函数的使用方法和各种文件模式
- 熟练进行文本文件的读写操作
- 理解二进制文件的处理方法
- 掌握文件对象的各种方法和属性
- 学会使用with语句进行安全的文件操作
- 理解文件编码和处理中文文本
- 掌握目录操作和文件系统管理
- 编写高效、安全的文件处理程序
核心知识点讲解
文件操作基础
在Python中,文件操作主要包括打开文件、读取文件内容、写入文件内容和关闭文件等步骤。
open()函数
open()函数是Python中用于打开文件的主要函数:
file_object = open(filename, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
主要参数说明:
filename:要打开的文件名mode:文件打开模式encoding:文件编码格式errors:错误处理方案
文件模式
常见的文件打开模式:
| 模式 | 描述 |
|---|---|
| 'r' | 只读模式(默认) |
| 'w' | 写入模式,会覆盖已有文件 |
| 'a' | 追加模式 |
| 'x' | 独占创建模式 |
| 'b' | 二进制模式 |
| 't' | 文本模式(默认) |
| '+' | 读写模式 |
组合使用示例:
'rb':二进制只读模式'w+':读写模式,会覆盖文件'a+':追加和读取模式
文本文件操作
读取文本文件
# 方法1:使用read()读取整个文件
try:
with open('example.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)
except FileNotFoundError:
print("文件未找到")
except Exception as e:
print(f"读取文件时出错: {e}")
# 方法2:使用readlines()按行读取
try:
with open('example.txt', 'r', encoding='utf-8') as file:
lines = file.readlines()
for line in lines:
print(line.strip()) # strip()去除行尾换行符
except FileNotFoundError:
print("文件未找到")
# 方法3:逐行读取(内存友好)
try:
with open('example.txt', 'r', encoding='utf-8') as file:
for line in file:
print(line.strip())
except FileNotFoundError:
print("文件未找到")
写入文本文件
# 方法1:使用write()写入
try:
with open('output.txt', 'w', encoding='utf-8') as file:
file.write("Hello, World!\n")
file.write("这是第二行内容。\n")
except Exception as e:
print(f"写入文件时出错: {e}")
# 方法2:使用writelines()写入多行
lines = ["第一行\n", "第二行\n", "第三行\n"]
try:
with open('output.txt', 'w', encoding='utf-8') as file:
file.writelines(lines)
except Exception as e:
print(f"写入文件时出错: {e}")
# 方法3:追加模式写入
try:
with open('output.txt', 'a', encoding='utf-8') as file:
file.write("这是追加的内容。\n")
except Exception as e:
print(f"追加文件时出错: {e}")
二进制文件操作
二进制文件操作主要用于处理图片、音频、视频等非文本文件。
读取二进制文件
# 读取图片文件
try:
with open('image.jpg', 'rb') as file:
binary_data = file.read()
print(f"文件大小: {len(binary_data)} 字节")
except FileNotFoundError:
print("文件未找到")
except Exception as e:
print(f"读取二进制文件时出错: {e}")
写入二进制文件
# 写入二进制数据
binary_data = b'\x89PNG\r\n\x1a\n' # PNG文件头
try:
with open('output.bin', 'wb') as file:
file.write(binary_data)
except Exception as e:
print(f"写入二进制文件时出错: {e}")
复制二进制文件
def copy_binary_file(source, destination):
"""复制二进制文件"""
try:
with open(source, 'rb') as src_file:
with open(destination, 'wb') as dst_file:
# 分块读取和写入,适用于大文件
chunk_size = 8192 # 8KB块大小
while True:
chunk = src_file.read(chunk_size)
if not chunk:
break
dst_file.write(chunk)
print(f"文件复制成功: {source} -> {destination}")
except Exception as e:
print(f"复制文件时出错: {e}")
# 使用示例
# copy_binary_file('source.jpg', 'destination.jpg')
文件对象方法
文件对象提供了许多有用的方法:
try:
with open('example.txt', 'r+', encoding='utf-8') as file:
# 读取方法
content = file.read() # 读取整个文件
file.seek(0) # 移动到文件开头
first_line = file.readline() # 读取一行
file.seek(0) # 重新移动到文件开头
all_lines = file.readlines() # 读取所有行
# 写入方法
file.write("新内容\n") # 写入内容
file.writelines(["行1\n", "行2\n"]) # 写入多行
# 文件位置相关
position = file.tell() # 获取当前位置
file.seek(0) # 移动到指定位置
file.seek(0, 2) # 移动到文件末尾(0偏移,2表示从末尾开始)
# 其他方法
file.flush() # 刷新缓冲区
is_closed = file.closed # 检查文件是否已关闭
file_mode = file.mode # 获取文件模式
file_name = file.name # 获取文件名
except Exception as e:
print(f"文件操作时出错: {e}")
文件编码处理
处理不同编码的文件是实际开发中的常见需求:
# 处理UTF-8编码文件
try:
with open('utf8_file.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)
except UnicodeDecodeError as e:
print(f"编码错误: {e}")
# 处理GBK编码文件(常见于Windows中文系统)
try:
with open('gbk_file.txt', 'r', encoding='gbk') as file:
content = file.read()
print(content)
except UnicodeDecodeError as e:
print(f"编码错误: {e}")
# 自动检测编码(需要安装chardet库)
# pip install chardet
try:
import chardet
# 检测文件编码
with open('unknown_encoding.txt', 'rb') as file:
raw_data = file.read()
encoding_info = chardet.detect(raw_data)
encoding = encoding_info['encoding']
print(f"检测到的编码: {encoding}")
# 使用检测到的编码读取文件
with open('unknown_encoding.txt', 'r', encoding=encoding) as file:
content = file.read()
print(content)
except ImportError:
print("请安装chardet库: pip install chardet")
except Exception as e:
print(f"处理文件时出错: {e}")
目录和文件系统操作
Python的os和os.path模块提供了丰富的目录和文件系统操作功能:
import os
import shutil
from pathlib import Path
# 获取当前工作目录
current_dir = os.getcwd()
print(f"当前工作目录: {current_dir}")
# 列出目录内容
try:
files = os.listdir('.')
print("当前目录下的文件和目录:")
for item in files:
print(f" {item}")
except Exception as e:
print(f"列出目录内容时出错: {e}")
# 创建目录
try:
os.mkdir('new_directory')
print("目录创建成功")
except FileExistsError:
print("目录已存在")
except Exception as e:
print(f"创建目录时出错: {e}")
# 递归创建目录
try:
os.makedirs('parent/child/grandchild', exist_ok=True)
print("递归目录创建成功")
except Exception as e:
print(f"递归创建目录时出错: {e}")
# 检查文件或目录是否存在
if os.path.exists('example.txt'):
print("文件存在")
else:
print("文件不存在")
if os.path.isdir('new_directory'):
print("这是一个目录")
elif os.path.isfile('example.txt'):
print("这是一个文件")
# 获取文件信息
if os.path.exists('example.txt'):
stat_info = os.stat('example.txt')
print(f"文件大小: {stat_info.st_size} 字节")
print(f"修改时间: {stat_info.st_mtime}")
# 删除文件和目录
try:
os.remove('unwanted_file.txt')
print("文件删除成功")
except FileNotFoundError:
print("文件不存在")
except Exception as e:
print(f"删除文件时出错: {e}")
try:
os.rmdir('empty_directory')
print("空目录删除成功")
except OSError as e:
print(f"删除目录时出错: {e}")
# 使用shutil进行高级操作
try:
shutil.copy('source.txt', 'destination.txt') # 复制文件
shutil.move('old_name.txt', 'new_name.txt') # 移动/重命名文件
shutil.rmtree('directory_to_delete') # 删除非空目录
print("高级文件操作完成")
except Exception as e:
print(f"高级文件操作时出错: {e}")
# 使用pathlib(Python 3.4+推荐方式)
path = Path('example.txt')
# 检查路径是否存在
if path.exists():
print("路径存在")
# 检查是否为文件
if path.is_file():
print("这是一个文件")
# 检查是否为目录
if path.is_dir():
print("这是一个目录")
# 获取文件扩展名
print(f"文件扩展名: {path.suffix}")
# 获取文件名(不含扩展名)
print(f"文件名: {path.stem}")
# 获取父目录
print(f"父目录: {path.parent}")
临时文件和目录
有时我们需要创建临时文件进行操作:
import tempfile
import os
# 创建临时文件
with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.txt') as temp_file:
temp_file.write("这是临时文件的内容")
temp_filename = temp_file.name
print(f"临时文件名: {temp_filename}")
# 读取临时文件
try:
with open(temp_filename, 'r', encoding='utf-8') as file:
content = file.read()
print(f"临时文件内容: {content}")
finally:
# 清理临时文件
os.unlink(temp_filename)
print("临时文件已删除")
# 创建临时目录
with tempfile.TemporaryDirectory() as temp_dir:
print(f"临时目录: {temp_dir}")
# 在临时目录中创建文件
temp_file_path = os.path.join(temp_dir, 'temp_file.txt')
with open(temp_file_path, 'w', encoding='utf-8') as file:
file.write("临时目录中的文件")
# 读取文件
with open(temp_file_path, 'r', encoding='utf-8') as file:
content = file.read()
print(f"文件内容: {content}")
# 临时目录在此处自动删除
print("临时目录已自动删除")
CSV文件处理
CSV(Comma-Separated Values)是一种常见的数据存储格式:
import csv
# 写入CSV文件
data = [
['姓名', '年龄', '城市'],
['张三', '25', '北京'],
['李四', '30', '上海'],
['王五', '28', '广州']
]
try:
with open('data.csv', 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(data)
print("CSV文件写入成功")
except Exception as e:
print(f"写入CSV文件时出错: {e}")
# 读取CSV文件
try:
with open('data.csv', 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
print(row)
except Exception as e:
print(f"读取CSV文件时出错: {e}")
# 使用DictReader和DictWriter
# 写入字典格式的CSV
dict_data = [
{'姓名': '张三', '年龄': '25', '城市': '北京'},
{'姓名': '李四', '年龄': '30', '城市': '上海'},
{'姓名': '王五', '年龄': '28', '城市': '广州'}
]
try:
with open('dict_data.csv', 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['姓名', '年龄', '城市']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader() # 写入表头
writer.writerows(dict_data)
print("字典格式CSV文件写入成功")
except Exception as e:
print(f"写入字典格式CSV文件时出错: {e}")
# 读取字典格式的CSV
try:
with open('dict_data.csv', 'r', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
print(f"姓名: {row['姓名']}, 年龄: {row['年龄']}, 城市: {row['城市']}")
except Exception as e:
print(f"读取字典格式CSV文件时出错: {e}")
代码示例与实战
示例1:日志文件处理器
import os
import datetime
from typing import List, Optional
class LogFileProcessor:
"""日志文件处理器"""
def __init__(self, log_directory: str = "logs"):
self.log_directory = log_directory
self._ensure_log_directory()
def _ensure_log_directory(self):
"""确保日志目录存在"""
if not os.path.exists(self.log_directory):
os.makedirs(self.log_directory)
def write_log(self, message: str, level: str = "INFO") -> bool:
"""写入日志"""
try:
# 生成日志文件名(按天分割)
today = datetime.datetime.now().strftime("%Y-%m-%d")
log_filename = os.path.join(self.log_directory, f"log_{today}.txt")
# 获取当前时间
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 格式化日志行
log_entry = f"[{timestamp}] [{level}] {message}\n"
# 追加写入日志文件
with open(log_filename, 'a', encoding='utf-8') as log_file:
log_file.write(log_entry)
return True
except Exception as e:
print(f"写入日志时出错: {e}")
return False
def read_logs(self, date: Optional[str] = None) -> List[str]:
"""读取日志"""
try:
if date is None:
date = datetime.datetime.now().strftime("%Y-%m-%d")
log_filename = os.path.join(self.log_directory, f"log_{date}.txt")
if not os.path.exists(log_filename):
return []
with open(log_filename, 'r', encoding='utf-8') as log_file:
return log_file.readlines()
except Exception as e:
print(f"读取日志时出错: {e}")
return []
def search_logs(self, keyword: str, date: Optional[str] = None) -> List[str]:
"""搜索日志"""
logs = self.read_logs(date)
matching_logs = []
for log_line in logs:
if keyword.lower() in log_line.lower():
matching_logs.append(log_line.strip())
return matching_logs
def get_log_files(self) -> List[str]:
"""获取所有日志文件"""
try:
files = os.listdir(self.log_directory)
log_files = [f for f in files if f.startswith("log_") and f.endswith(".txt")]
return sorted(log_files)
except Exception as e:
print(f"获取日志文件列表时出错: {e}")
return []
def clear_old_logs(self, days_to_keep: int = 7) -> int:
"""清理旧日志文件"""
try:
import datetime
now = datetime.datetime.now()
deleted_count = 0
log_files = self.get_log_files()
for log_file in log_files:
# 解析文件名中的日期
try:
date_str = log_file[4:-4] # 去掉"log_"前缀和".txt"后缀
file_date = datetime.datetime.strptime(date_str, "%Y-%m-%d")
# 计算文件年龄
age = (now - file_date).days
# 如果文件太旧,删除它
if age > days_to_keep:
file_path = os.path.join(self.log_directory, log_file)
os.remove(file_path)
deleted_count += 1
print(f"已删除旧日志文件: {log_file}")
except ValueError:
# 如果无法解析日期,跳过该文件
continue
return deleted_count
except Exception as e:
print(f"清理旧日志时出错: {e}")
return 0
def main():
# 创建日志处理器
logger = LogFileProcessor()
# 写入一些测试日志
logger.write_log("应用程序启动", "INFO")
logger.write_log("用户登录成功", "INFO")
logger.write_log("数据库连接失败", "ERROR")
logger.write_log("处理用户请求", "DEBUG")
logger.write_log("用户登出", "INFO")
logger.write_log("内存不足警告", "WARNING")
# 读取今天的日志
print("=== 今日日志 ===")
today_logs = logger.read_logs()
for log in today_logs:
print(log.strip())
# 搜索包含特定关键词的日志
print("\n=== 错误日志 ===")
error_logs = logger.search_logs("error")
for log in error_logs:
print(log)
# 显示所有日志文件
print("\n=== 日志文件列表 ===")
log_files = logger.get_log_files()
for log_file in log_files:
print(log_file)
# 清理3天前的日志(这里只是演示,实际使用时要小心)
# deleted = logger.clear_old_logs(3)
# print(f"\n已清理 {deleted} 个旧日志文件")
if __name__ == "__main__":
main()
示例2:配置文件管理器
import json
import os
from typing import Any, Dict, Optional
class ConfigManager:
"""配置文件管理器"""
def __init__(self, config_file: str = "config.json"):
self.config_file = config_file
self.config = {}
self.load_config()
def load_config(self) -> bool:
"""加载配置文件"""
try:
if os.path.exists(self.config_file):
with open(self.config_file, 'r', encoding='utf-8') as file:
self.config = json.load(file)
print(f"配置文件加载成功: {self.config_file}")
return True
else:
print(f"配置文件不存在,使用默认配置: {self.config_file}")
self.config = self.get_default_config()
return False
except json.JSONDecodeError as e:
print(f"配置文件格式错误: {e}")
self.config = self.get_default_config()
return False
except Exception as e:
print(f"加载配置文件时出错: {e}")
self.config = self.get_default_config()
return False
def save_config(self) -> bool:
"""保存配置文件"""
try:
# 确保目录存在
directory = os.path.dirname(self.config_file)
if directory and not os.path.exists(directory):
os.makedirs(directory)
with open(self.config_file, 'w', encoding='utf-8') as file:
json.dump(self.config, file, ensure_ascii=False, indent=2)
print(f"配置文件保存成功: {self.config_file}")
return True
except Exception as e:
print(f"保存配置文件时出错: {e}")
return False
def get_default_config(self) -> Dict[str, Any]:
"""获取默认配置"""
return {
"app_name": "MyApplication",
"version": "1.0.0",
"debug": False,
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp_db"
},
"logging": {
"level": "INFO",
"file": "app.log"
},
"features": {
"enable_cache": True,
"max_connections": 100
}
}
def get(self, key: str, default: Any = None) -> Any:
"""获取配置项"""
keys = key.split('.')
value = self.config
try:
for k in keys:
value = value[k]
return value
except (KeyError, TypeError):
return default
def set(self, key: str, value: Any) -> None:
"""设置配置项"""
keys = key.split('.')
config = self.config
# 导航到倒数第二层
for k in keys[:-1]:
if k not in config:
config[k] = {}
config = config[k]
# 设置最后一层的值
config[keys[-1]] = value
def update(self, updates: Dict[str, Any]) -> None:
"""批量更新配置"""
for key, value in updates.items():
self.set(key, value)
def reset_to_default(self) -> None:
"""重置为默认配置"""
self.config = self.get_default_config()
def validate_config(self) -> bool:
"""验证配置"""
required_keys = ["app_name", "version"]
for key in required_keys:
if key not in self.config:
print(f"缺少必需的配置项: {key}")
return False
return True
def display_config(self) -> None:
"""显示当前配置"""
print("=== 当前配置 ===")
print(json.dumps(self.config, ensure_ascii=False, indent=2))
def main():
# 创建配置管理器
config_manager = ConfigManager("app_config.json")
# 显示当前配置
config_manager.display_config()
# 修改一些配置项
config_manager.set("app_name", "超级应用")
config_manager.set("database.host", "192.168.1.100")
config_manager.set("logging.level", "DEBUG")
# 批量更新配置
updates = {
"debug": True,
"features.max_connections": 200
}
config_manager.update(updates)
# 获取配置项
app_name = config_manager.get("app_name")
db_host = config_manager.get("database.host")
debug_mode = config_manager.get("debug", False)
print(f"\n应用名称: {app_name}")
print(f"数据库主机: {db_host}")
print(f"调试模式: {debug_mode}")
# 验证配置
if config_manager.validate_config():
print("\n配置验证通过")
else:
print("\n配置验证失败")
# 保存配置
if config_manager.save_config():
print("配置已保存")
else:
print("配置保存失败")
# 重新加载配置以验证保存是否成功
print("\n=== 重新加载配置 ===")
config_manager.load_config()
config_manager.display_config()
if __name__ == "__main__":
main()
示例3:文件批量处理工具
import os
import shutil
import hashlib
from typing import List, Tuple, Optional
from pathlib import Path
class BatchFileProcessor:
"""批量文件处理器"""
def __init__(self):
self.processed_files = []
self.errors = []
def find_files(self, directory: str, extension: Optional[str] = None,
recursive: bool = True) -> List[str]:
"""查找文件"""
try:
path = Path(directory)
pattern = f"*.{extension}" if extension else "*"
if recursive:
files = list(path.rglob(pattern))
else:
files = list(path.glob(pattern))
# 过滤掉目录,只保留文件
files = [str(f) for f in files if f.is_file()]
return sorted(files)
except Exception as e:
print(f"查找文件时出错: {e}")
return []
def calculate_file_hash(self, filepath: str, algorithm: str = "md5") -> Optional[str]:
"""计算文件哈希值"""
try:
hash_obj = hashlib.new(algorithm)
with open(filepath, 'rb') as file:
# 分块读取文件以节省内存
for chunk in iter(lambda: file.read(4096), b""):
hash_obj.update(chunk)
return hash_obj.hexdigest()
except Exception as e:
print(f"计算文件哈希时出错 {filepath}: {e}")
return None
def copy_files(self, source_files: List[str], destination_dir: str,
preserve_structure: bool = False) -> Tuple[int, int]:
"""复制文件"""
success_count = 0
error_count = 0
# 确保目标目录存在
Path(destination_dir).mkdir(parents=True, exist_ok=True)
for source_file in source_files:
try:
source_path = Path(source_file)
if preserve_structure:
# 保持目录结构
relative_path = source_path.relative_to(source_path.parent.parent)
dest_path = Path(destination_dir) / relative_path
else:
# 扁平化复制
dest_path = Path(destination_dir) / source_path.name
# 确保目标文件的目录存在
dest_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source_file, dest_path)
print(f"已复制: {source_file} -> {dest_path}")
success_count += 1
except Exception as e:
print(f"复制文件失败 {source_file}: {e}")
error_count += 1
self.errors.append(f"复制失败 {source_file}: {e}")
return success_count, error_count
def rename_files(self, file_mapping: Dict[str, str]) -> Tuple[int, int]:
"""重命名文件"""
success_count = 0
error_count = 0
for old_name, new_name in file_mapping.items():
try:
old_path = Path(old_name)
new_path = old_path.parent / new_name
old_path.rename(new_path)
print(f"已重命名: {old_name} -> {new_name}")
success_count += 1
except Exception as e:
print(f"重命名文件失败 {old_name}: {e}")
error_count += 1
self.errors.append(f"重命名失败 {old_name}: {e}")
return success_count, error_count
def remove_duplicates(self, files: List[str], dry_run: bool = True) -> Tuple[int, int]:
"""移除重复文件"""
file_hashes = {}
duplicates = []
print("正在计算文件哈希值...")
for filepath in files:
file_hash = self.calculate_file_hash(filepath)
if file_hash:
if file_hash in file_hashes:
duplicates.append((filepath, file_hashes[file_hash]))
else:
file_hashes[file_hash] = filepath
duplicate_count = len(duplicates)
removed_count = 0
print(f"发现 {duplicate_count} 个重复文件")
if dry_run:
print("=== 重复文件列表(预览模式)===")
for dup, orig in duplicates:
print(f" 重复: {dup}")
print(f" 原始: {orig}")
print()
else:
print("正在移除重复文件...")
for duplicate_file, _ in duplicates:
try:
os.remove(duplicate_file)
print(f"已删除重复文件: {duplicate_file}")
removed_count += 1
except Exception as e:
print(f"删除文件失败 {duplicate_file}: {e}")
self.errors.append(f"删除失败 {duplicate_file}: {e}")
return duplicate_count, removed_count
def get_file_info(self, filepath: str) -> Optional[Dict[str, Any]]:
"""获取文件信息"""
try:
path = Path(filepath)
stat = path.stat()
return {
"name": path.name,
"size": stat.st_size,
"created": stat.st_ctime,
"modified": stat.st_mtime,
"is_file": path.is_file(),
"is_dir": path.is_dir(),
"extension": path.suffix,
"hash": self.calculate_file_hash(filepath)
}
except Exception as e:
print(f"获取文件信息失败 {filepath}: {e}")
return None
def batch_process(self, directory: str, operations: List[str],
**kwargs) -> Dict[str, Any]:
"""批处理操作"""
results = {
"processed_files": 0,
"success_count": 0,
"error_count": 0,
"details": {}
}
# 查找文件
extension = kwargs.get("extension")
files = self.find_files(directory, extension)
results["processed_files"] = len(files)
print(f"找到 {len(files)} 个文件")
# 执行操作
for operation in operations:
if operation == "copy":
dest_dir = kwargs.get("destination")
if dest_dir:
success, error = self.copy_files(files, dest_dir)
results["success_count"] += success
results["error_count"] += error
results["details"]["copy"] = {"success": success, "error": error}
elif operation == "remove_duplicates":
dry_run = kwargs.get("dry_run", True)
dup_count, removed_count = self.remove_duplicates(files, dry_run)
results["details"]["remove_duplicates"] = {
"duplicates_found": dup_count,
"removed": removed_count
}
return results
def main():
processor = BatchFileProcessor()
# 创建测试目录和文件
test_dir = "test_files"
Path(test_dir).mkdir(exist_ok=True)
# 创建一些测试文件
test_files = [
"document1.txt",
"document2.txt",
"image1.jpg",
"image2.jpg",
"data1.csv",
"data2.csv"
]
for filename in test_files:
filepath = Path(test_dir) / filename
with open(filepath, 'w', encoding='utf-8') as f:
f.write(f"这是测试文件 {filename} 的内容")
# 查找文件
print("=== 查找文件 ===")
txt_files = processor.find_files(test_dir, "txt")
print(f"找到 {len(txt_files)} 个txt文件:")
for file in txt_files:
print(f" {file}")
# 计算文件哈希
print("\n=== 文件哈希 ===")
for file in txt_files[:2]: # 只计算前两个文件的哈希
file_hash = processor.calculate_file_hash(file)
print(f"{file}: {file_hash}")
# 获取文件信息
print("\n=== 文件信息 ===")
if txt_files:
file_info = processor.get_file_info(txt_files[0])
if file_info:
print(f"文件名: {file_info['name']}")
print(f"大小: {file_info['size']} 字节")
print(f"扩展名: {file_info['extension']}")
print(f"哈希: {file_info['hash']}")
# 批量复制文件
print("\n=== 批量复制文件 ===")
copy_results = processor.batch_process(
directory=test_dir,
operations=["copy"],
extension="txt",
destination="copied_files"
)
print(f"复制结果: {copy_results}")
# 清理测试文件
try:
shutil.rmtree(test_dir)
shutil.rmtree("copied_files")
print("\n测试文件已清理")
except Exception as e:
print(f"清理测试文件时出错: {e}")
if __name__ == "__main__":
main()
小结与回顾
在本章中,我们深入学习了Python的文件操作机制:
-
文件操作基础:
- 掌握了
open()函数的使用方法和各种文件模式 - 理解了文本文件和二进制文件的区别
- 掌握了
-
文本文件处理:
- 学会了读取和写入文本文件的各种方法
- 掌握了逐行处理大文件的技术
-
二进制文件处理:
- 理解了二进制文件的操作方法
- 学会了处理图片、音频等非文本文件
-
文件系统操作:
- 掌握了目录操作和文件管理
- 学会了使用
os、shutil和pathlib模块
-
高级文件处理:
- 了解了临时文件的使用
- 掌握了CSV文件的处理方法
通过实际的代码示例,我们不仅掌握了理论知识,还学会了如何在实际项目中应用文件操作技术。文件操作是程序持久化存储数据的基础,掌握这些技能对于开发实用的应用程序非常重要。
在下一章中,我们将学习模块与包管理,帮助我们更好地组织和复用代码。
练习与挑战
基础练习
- 编写一个程序,读取文本文件并统计其中的单词数量和行数。
- 创建一个程序,合并多个文本文件到一个输出文件中。
- 实现一个简单的文件加密/解密工具,使用基本的字符替换算法。
- 编写一个程序,递归遍历目录并列出所有文件及其大小。
进阶挑战
- 设计一个完整的备份工具,支持增量备份、压缩和定时备份功能。
- 创建一个文件同步工具,能够在两个目录之间同步文件变化。
- 实现一个日志分析工具,能够解析和分析Web服务器日志文件。
- 编写一个文档管理系统,支持文档的分类、搜索和版本控制。
思考题
- 在处理大文件时,为什么要避免一次性读取整个文件到内存中?
- 什么时候应该使用二进制模式而不是文本模式打开文件?
- 如何安全地处理文件编码问题,特别是在跨平台开发中?
- with语句在文件操作中有什么优势?为什么不直接使用open()和close()?
扩展阅读
- Python官方文档 - 文件和目录访问 - 官方文档中关于文件系统的详细介绍
- Python官方文档 - open()函数 - open()函数的详细说明
- Python官方文档 - pathlib模块 - 现代化的路径操作模块
- Python官方文档 - shutil模块 - 高级文件操作模块
- 《流畅的Python》- 深入理解Python文件操作的经典书籍
- Real Python - Reading and Writing Files - 关于Python文件操作的详细教程
- Real Python - Working with Files - 更深入的文件操作教程
通过本章的学习,你应该已经掌握了Python文件操作的核心概念和使用方法。这些知识将帮助你处理各种文件操作任务,为开发实用的应用程序奠定基础。在下一章中,我们将学习模块与包管理,帮助我们更好地组织和复用代码。