当前位置: 首页 > news >正文

Python3:文件操作

Python3:文件操作

    • 文件操作的基本流程
    • 一、打开文件:open() 函数
      • 常用的文件打开模式
    • 二、读取文件内容
      • 读取整个文件
      • 逐行读取(处理大文件的理想方式)
      • 读取指定数量的字符
    • 三、写入文件内容
      • 写入字符串
      • 写入多行
      • 使用 writelines() 写入多行
    • 四、追加内容到文件
    • 五、文件指针操作
    • 六、with 语句的好处
    • 七、处理二进制文件
    • 八、文件操作的实用例子
      • 例子1:复制文件
      • 例子2:文件内容统计
      • 例子3:简单的日志记录器
      • 例子4:CSV 文件处理
      • 例子5:简单的文件加密/解密
    • 九、处理路径的工具:os 和 pathlib 模块
      • 使用 os.path 模块
      • 使用现代的 pathlib 模块
    • 十、处理目录
      • 创建目录
      • 列出目录内容
      • 删除文件和目录
    • 十一、文件和目录的移动、复制和重命名
    • 十二、临时文件和目录
    • 十三、实际应用:简单的文件备份脚本
    • 小结:文件操作的最佳实践

文件操作是编程中的基础技能,Python 提供了简单而强大的文件处理功能。通过文件操作,你可以读取、写入、修改文件,实现数据的永久存储和共享。

文件操作的基本流程

  1. 打开文件
  2. 读取或写入数据
  3. 关闭文件

一、打开文件:open() 函数

file = open(filename, mode, encoding)

参数说明:

  • filename:文件路径
  • mode:打开模式(读、写、追加等)
  • encoding:字符编码(如 ‘utf-8’)

常用的文件打开模式

模式描述
'r'只读模式(默认)
'w'写入模式(会覆盖现有内容)
'a'追加模式(在文件末尾添加内容)
'x'创建模式(如果文件已存在则失败)
'b'二进制模式(与其他模式结合使用,如 'rb', 'wb'
't'文本模式(默认)
'+'读写模式(与其他模式结合使用,如 'r+', 'w+'

二、读取文件内容

读取整个文件

# 方法 1:读取所有内容为一个字符串
with open('example.txt', 'r', encoding='utf-8') as file:content = file.read()print(content)# 方法 2:读取所有行到一个列表
with open('example.txt', 'r', encoding='utf-8') as file:lines = file.readlines()for line in lines:print(line.strip())  # strip() 移除行尾的换行符

逐行读取(处理大文件的理想方式)

with open('example.txt', 'r', encoding='utf-8') as file:for line in file:print(line.strip())

读取指定数量的字符

with open('example.txt', 'r', encoding='utf-8') as file:# 读取前10个字符chunk = file.read(10)print(chunk)

三、写入文件内容

写入字符串

with open('output.txt', 'w', encoding='utf-8') as file:file.write("这是第一行\n")file.write("这是第二行\n")

写入多行

lines = ["第一行", "第二行", "第三行"]
with open('output.txt', 'w', encoding='utf-8') as file:for line in lines:file.write(line + '\n')

使用 writelines() 写入多行

lines = ["第一行\n", "第二行\n", "第三行\n"]
with open('output.txt', 'w', encoding='utf-8') as file:file.writelines(lines)

四、追加内容到文件

with open('output.txt', 'a', encoding='utf-8') as file:file.write("这是追加的一行\n")

五、文件指针操作

with open('example.txt', 'r', encoding='utf-8') as file:# 读取前5个字符print(file.read(5))# 获取当前位置position = file.tell()print(f"当前位置: {position}")# 移动到文件开头file.seek(0)print(f"回到开头后读取: {file.read(5)}")# 移动到特定位置file.seek(10)print(f"移动到第10个字节后读取: {file.read(5)}")

六、with 语句的好处

使用 with 语句(上下文管理器)打开文件的优点:

  • 自动关闭文件,即使发生异常
  • 代码更简洁、更易读
  • 避免资源泄漏
# 不推荐的方式
file = open('example.txt', 'r')
try:content = file.read()print(content)
finally:file.close()# 推荐的方式
with open('example.txt', 'r') as file:content = file.read()print(content)
# 文件在这里自动关闭

七、处理二进制文件

# 读取二进制文件
with open('image.jpg', 'rb') as file:binary_data = file.read()print(f"文件大小: {len(binary_data)} 字节")# 写入二进制文件
with open('copy.jpg', 'wb') as file:file.write(binary_data)

八、文件操作的实用例子

例子1:复制文件

def copy_file(source, destination):try:with open(source, 'rb') as src_file:with open(destination, 'wb') as dest_file:# 每次读取 1MBchunk_size = 1024 * 1024while True:chunk = src_file.read(chunk_size)if not chunk:breakdest_file.write(chunk)print(f"文件从 {source} 复制到 {destination} 成功!")return Trueexcept Exception as e:print(f"复制文件时出错: {e}")return False# 使用函数复制文件
copy_file('original.txt', 'backup.txt')

例子2:文件内容统计

def analyze_text_file(filename):try:with open(filename, 'r', encoding='utf-8') as file:content = file.read()# 基本统计char_count = len(content)word_count = len(content.split())line_count = content.count('\n') + 1  # +1 for the last line# 计算每个字符的出现频率char_freq = {}for char in content:if char in char_freq:char_freq[char] += 1else:char_freq[char] = 1# 排序并获取前5个最常见字符sorted_chars = sorted(char_freq.items(), key=lambda x: x[1], reverse=True)top_chars = sorted_chars[:5]# 打印统计结果print(f"文件:{filename}")print(f"字符数:{char_count}")print(f"单词数:{word_count}")print(f"行数:{line_count}")print("最常见的字符:")for char, count in top_chars:if char == '\n':char_name = '换行符'elif char == ' ':char_name = '空格'elif char == '\t':char_name = '制表符'else:char_name = charprint(f"  '{char_name}': {count}次")except Exception as e:print(f"分析文件时出错: {e}")# 分析文本文件
analyze_text_file('example.txt')

例子3:简单的日志记录器

import datetimedef log(message, log_file='app.log'):"""记录带时间戳的日志消息"""timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')log_entry = f"[{timestamp}] {message}\n"with open(log_file, 'a', encoding='utf-8') as file:file.write(log_entry)# 使用日志记录器
log("程序启动")
try:result = 10 / 0
except Exception as e:log(f"错误: {e}")
log("程序结束")

例子4:CSV 文件处理

import csv# 读取 CSV 文件
def read_csv(filename):data = []try:with open(filename, 'r', encoding='utf-8', newline='') as file:csv_reader = csv.reader(file)headers = next(csv_reader)  # 获取表头for row in csv_reader:data.append(row)print(f"读取了 {len(data)} 行数据")return headers, dataexcept Exception as e:print(f"读取CSV文件时出错: {e}")return None, None# 写入 CSV 文件
def write_csv(filename, headers, data):try:with open(filename, 'w', encoding='utf-8', newline='') as file:csv_writer = csv.writer(file)csv_writer.writerow(headers)  # 写入表头csv_writer.writerows(data)    # 写入数据行print(f"成功写入 {len(data)} 行数据")return Trueexcept Exception as e:print(f"写入CSV文件时出错: {e}")return False# 示例数据
headers = ['姓名', '年龄', '城市']
data = [['张三', '25', '北京'],['李四', '30', '上海'],['王五', '22', '广州']
]# 写入并读取CSV文件
write_csv('people.csv', headers, data)
read_headers, read_data = read_csv('people.csv')

例子5:简单的文件加密/解密

def xor_encrypt_decrypt(input_file, output_file, key):"""使用简单的XOR加密/解密文件注意:这只是演示用,不适合真实的加密需求"""try:with open(input_file, 'rb') as infile:data = infile.read()# 将密钥转换为字节if isinstance(key, str):key = key.encode()# XOR 操作(加密和解密是同一个操作)encrypted_data = bytearray()for i, byte in enumerate(data):key_byte = key[i % len(key)]encrypted_data.append(byte ^ key_byte)with open(output_file, 'wb') as outfile:outfile.write(encrypted_data)print(f"处理完成: {input_file} -> {output_file}")return Trueexcept Exception as e:print(f"处理文件时出错: {e}")return False# 使用XOR加密/解密
# 加密
xor_encrypt_decrypt('original.txt', 'encrypted.bin', 'secret_key')
# 解密(使用相同的密钥)
xor_encrypt_decrypt('encrypted.bin', 'decrypted.txt', 'secret_key')

九、处理路径的工具:os 和 pathlib 模块

使用 os.path 模块

import os# 获取当前工作目录
current_dir = os.getcwd()
print(f"当前目录: {current_dir}")# 拼接路径
file_path = os.path.join(current_dir, 'data', 'example.txt')
print(f"文件路径: {file_path}")# 检查路径是否存在
if os.path.exists(file_path):print(f"{file_path} 存在")
else:print(f"{file_path} 不存在")# 区分文件和目录
if os.path.isfile(file_path):print(f"{file_path} 是文件")
elif os.path.isdir(file_path):print(f"{file_path} 是目录")# 获取文件信息
if os.path.exists(file_path):size = os.path.getsize(file_path)modified_time = os.path.getmtime(file_path)print(f"文件大小: {size} 字节")print(f"修改时间: {modified_time}")# 分割路径
dirname, filename = os.path.split(file_path)
print(f"目录: {dirname}")
print(f"文件名: {filename}")# 分割文件名和扩展名
name, ext = os.path.splitext(filename)
print(f"文件名(无扩展名): {name}")
print(f"扩展名: {ext}")

使用现代的 pathlib 模块

from pathlib import Path# 创建路径对象
current_dir = Path.cwd()
print(f"当前目录: {current_dir}")# 构建路径
file_path = current_dir / 'data' / 'example.txt'
print(f"文件路径: {file_path}")# 检查路径是否存在
if file_path.exists():print(f"{file_path} 存在")
else:print(f"{file_path} 不存在")# 区分文件和目录
if file_path.is_file():print(f"{file_path} 是文件")
elif file_path.is_dir():print(f"{file_path} 是目录")# 获取文件信息
if file_path.exists():size = file_path.stat().st_sizemodified_time = file_path.stat().st_mtimeprint(f"文件大小: {size} 字节")print(f"修改时间: {modified_time}")# 获取路径组件
print(f"父目录: {file_path.parent}")
print(f"文件名: {file_path.name}")
print(f"文件名(无扩展名): {file_path.stem}")
print(f"扩展名: {file_path.suffix}")# 遍历目录
if current_dir.is_dir():print("目录中的文件:")for item in current_dir.iterdir():print(f"  {'目录' if item.is_dir() else '文件'}: {item.name}")

十、处理目录

创建目录

import os
from pathlib import Path# 使用 os 模块
if not os.path.exists('new_folder'):os.mkdir('new_folder')  # 创建单个目录print("目录已创建")if not os.path.exists('path/to/nested/folder'):os.makedirs('path/to/nested/folder')  # 创建多级目录print("多级目录已创建")# 使用 pathlib 模块
folder = Path('another_folder')
if not folder.exists():folder.mkdir()print("另一个目录已创建")nested_folder = Path('another/nested/folder')
if not nested_folder.exists():nested_folder.mkdir(parents=True)  # 创建多级目录print("另一个多级目录已创建")

列出目录内容

import os
from pathlib import Path# 使用 os 模块
folder_path = 'data'
if os.path.exists(folder_path) and os.path.isdir(folder_path):print(f"{folder_path} 中的内容:")# 列出文件和目录items = os.listdir(folder_path)for item in items:item_path = os.path.join(folder_path, item)item_type = "目录" if os.path.isdir(item_path) else "文件"print(f"  {item_type}: {item}")# 只列出文件files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]print(f"{folder_path} 中的文件: {files}")# 使用 pathlib 模块
folder = Path('data')
if folder.exists() and folder.is_dir():print(f"{folder} 中的内容:")# 列出所有内容for item in folder.iterdir():item_type = "目录" if item.is_dir() else "文件"print(f"  {item_type}: {item.name}")# 只列出文件files = [item.name for item in folder.iterdir() if item.is_file()]print(f"{folder} 中的文件: {files}")# 使用通配符查找特定文件txt_files = list(folder.glob('*.txt'))print(f"{folder} 中的文本文件: {[f.name for f in txt_files]}")# 递归查找所有子目录中的文件all_txt_files = list(folder.glob('**/*.txt'))print(f"所有子目录中的文本文件: {[f.name for f in all_txt_files]}")

删除文件和目录

import os
import shutil
from pathlib import Path# 删除文件
if os.path.exists('temp.txt'):os.remove('temp.txt')print("文件已删除")# 删除空目录
if os.path.exists('empty_folder') and os.path.isdir('empty_folder'):os.rmdir('empty_folder')  # 只能删除空目录print("空目录已删除")# 删除非空目录(及其所有内容)
if os.path.exists('non_empty_folder') and os.path.isdir('non_empty_folder'):shutil.rmtree('non_empty_folder')print("非空目录及其内容已删除")# 使用 pathlib(Python 3.8+)
file_path = Path('another_temp.txt')
if file_path.exists():file_path.unlink()  # 删除文件print("另一个文件已删除")dir_path = Path('another_empty_folder')
if dir_path.exists() and dir_path.is_dir():dir_path.rmdir()  # 只能删除空目录print("另一个空目录已删除")

十一、文件和目录的移动、复制和重命名

import os
import shutil
from pathlib import Path# 重命名文件或目录
if os.path.exists('old_name.txt'):os.rename('old_name.txt', 'new_name.txt')print("文件已重命名")# 移动文件或目录
if os.path.exists('source_file.txt'):shutil.move('source_file.txt', 'destination/source_file.txt')print("文件已移动")# 复制文件
if os.path.exists('original.txt'):shutil.copy('original.txt', 'copy.txt')  # 复制文件print("文件已复制")shutil.copy2('original.txt', 'copy2.txt')  # 复制文件(保留元数据)print("文件已复制(带元数据)")# 复制目录
if os.path.exists('original_dir') and os.path.isdir('original_dir'):shutil.copytree('original_dir', 'copy_dir')  # 复制整个目录树print("目录树已复制")# 使用 pathlib 重命名
file_path = Path('old_path.txt')
if file_path.exists():file_path.rename('new_path.txt')print("文件已使用 pathlib 重命名")

十二、临时文件和目录

import tempfile
import os# 创建临时文件
with tempfile.NamedTemporaryFile(delete=False) as temp_file:temp_name = temp_file.nametemp_file.write(b"这是临时文件的内容")print(f"临时文件创建于: {temp_name}")# 使用临时文件
with open(temp_name, 'r') as file:content = file.read()print(f"临时文件内容: {content}")# 删除临时文件
os.unlink(temp_name)
print("临时文件已删除")# 创建临时目录
temp_dir = tempfile.mkdtemp()
print(f"临时目录创建于: {temp_dir}")# 在临时目录中创建文件
temp_file_path = os.path.join(temp_dir, 'example.txt')
with open(temp_file_path, 'w') as file:file.write("临时目录中的文件内容")# 清理临时目录
import shutil
shutil.rmtree(temp_dir)
print("临时目录已删除")

十三、实际应用:简单的文件备份脚本

import os
import shutil
import datetime
import zipfiledef backup_folder(source_dir, backup_dir=None):"""创建指定文件夹的备份压缩文件Args:source_dir: 要备份的源目录backup_dir: 备份文件存放目录,默认为当前目录Returns:backup_path: 备份文件的完整路径"""# 源目录必须存在if not os.path.exists(source_dir):print(f"错误: 源目录 '{source_dir}' 不存在")return None# 默认备份到当前目录if backup_dir is None:backup_dir = os.getcwd()# 确保备份目录存在if not os.path.exists(backup_dir):os.makedirs(backup_dir)try:# 创建带时间戳的备份文件名source_name = os.path.basename(source_dir)timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")backup_filename = f"{source_name}_backup_{timestamp}.zip"backup_path = os.path.join(backup_dir, backup_filename)# 创建 ZIP 文件print(f"正在创建备份: {backup_path}")with zipfile.ZipFile(backup_path, 'w', zipfile.ZIP_DEFLATED) as zipf:# 遍历源目录中的所有文件和子目录for root, dirs, files in os.walk(source_dir):# 计算相对路径,保持目录结构rel_path = os.path.relpath(root, os.path.dirname(source_dir))if rel_path == '.':rel_path = source_nameelse:rel_path = os.path.join(source_name, rel_path)# 添加空目录for dir_name in dirs:dir_path = os.path.join(rel_path, dir_name)zipf.write(os.path.join(root, dir_name), dir_path)# 添加文件for file_name in files:file_path = os.path.join(rel_path, file_name)zipf.write(os.path.join(root, file_name), file_path)print(f"备份完成: {backup_path}")# 获取备份文件大小backup_size = os.path.getsize(backup_path)print(f"备份文件大小: {backup_size / (1024*1024):.2f} MB")return backup_pathexcept Exception as e:print(f"备份过程中出错: {e}")return None# 使用备份函数
if __name__ == "__main__":# 要备份的目录source_directory = "important_data"# 备份目录backup_directory = "backups"# 执行备份backup_file = backup_folder(source_directory, backup_directory)if backup_file:print(f"备份文件已保存到: {backup_file}")else:print("备份失败")

小结:文件操作的最佳实践

  1. 始终使用 with 语句打开文件,确保文件正确关闭
  2. 指定字符编码,通常使用 utf-8
  3. 使用适当的错误处理,处理可能的异常
  4. 对于大文件,逐行或分块处理,避免一次性加载整个文件
  5. 对于路径操作,优先使用 pathlib 模块(Python 3.4+)
  6. 使用有意义的文件名和路径,按照应用程序的组织结构
  7. 备份重要文件,特别是在执行可能修改文件的操作之前
  8. 注意文件权限,特别是在不同操作系统之间
  9. 验证文件操作的结果,确保数据已正确写入/读取

相关文章:

  • Lesar: 面向 Lustre/Scade 语言的形式化模型检测工具
  • vue前端SSE工具库|EventSource 替代方案推荐|PUSDN平行宇宙软件开发者网
  • Linux上安装Mysql、Redis、Nginx
  • Android 14 修改侧滑手势动画效果
  • C语言面试高频题——strcat、strncat、strcmp、strcpy 哪些函数会导致内存溢出?
  • Android ActivityManagerService(AMS)深度解析
  • 基于javaweb的SpringBoot+MyBatis通讯录管理系统设计与实现(源码+文档+部署讲解)
  • 【维护窗口内最值+单调队列/优先队列】Leetcode 239. 滑动窗口最大值
  • Echarts 问题:自定义的 legend 点击后消失,格式化 legend 的隐藏文本样式
  • PowerShell脚本实现|从文件夹动画序列中均匀选取关键帧(保留首尾帧)
  • redis 数据类型新手练习系列——string类型
  • 【QQMusic项目复习笔记——音乐管理模块详解】第四章
  • Doris vs ClickHouse:深入对比MPP数据库聚合操作的核心区别
  • 重读《人件》Peopleware -(9-1)Ⅱ办公环境Ⅱ“你在这儿从早上9点到下午5点之间什么都做不成.“(上)
  • 2025 年导游证报考条件新政策解读与应对策略
  • 同样机身尺寸下伺服电机比无刷电机扭矩更大的原因
  • LangChain LCEL表达式语言简介
  • IP SSL证书常见问题助您快速实现HTTPS加密
  • ElementUi的tabs样式太难修改,自定义tabs标签页
  • Leetcode 2845 题解
  • 视频丨伊朗阿巴斯港一处油罐发生高强度爆炸:造成大面积破坏,伤亡不明
  • 最高法知产庭年度报告:民事案件二审发回重审率持续下降
  • 贵州通报9起群众身边不正之风和腐败问题典型案例
  • “五一”假期云南铁路预计发送旅客超330万人次
  • 胃病、闭经、湿疹、失明:藏在疾病后的情绪问题
  • 双拥主题歌曲MV:爱我人民,爱我军