不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。
python系列之文件操作:让程序拥有"记忆"的超能力!
python系列前期章节
- python系列之注释与变量
- python系列之输入输出语句与数据类型
- python系列之运算符
- python系列之控制流程语句
- python系列之字符串
- python系列之列表
- python系列之元组
- python系列之字典
- python系列之集合
- python系列之函数基础
- python系列之函数进阶
- python系统之综合案例1:用python打造智能诗词生成助手
- python系列之综合案例2:用python开发《魔法学院入学考试》文字冒险游戏
- python系列之类与对象:面向对象编程(用造人计划秒懂面向对象)
- python系列之类与对象:python系列之详解面向对象的属性)
- python系列之详解面向对象的函数
- python系列之面向对象的三大特性
- python系列之异常处理:给代码穿上“防弹衣”
阅读建议:想象自己是一名数据魔法师,正在学习如何读取、写入和操控信息的奥秘!📁✨
一、前言:为什么需要文件操作?
想象一下:你写了一个很棒的程序,但每次关闭后,所有数据都消失了。就像用粉笔在黑板上写字,一擦就没了!
文件操作让程序能够:
- 📝 保存数据:游戏进度、用户设置、计算结果
- 📖 读取数据:配置文件、数据库、日志文件
- 🔄 交换数据:与其他程序共享信息
二、文件操作的基本步骤:打开→操作→关闭
文件操作就像读书一样简单:
- 打开书(打开文件)
- 读书或写字(读取或写入)
- 合上书(关闭文件)
# 基本文件操作流程
file = open("example.txt", "r") # 1. 打开文件
content = file.read() # 2. 读取内容
file.close() # 3. 关闭文件
三、文件打开模式:不同的"读书方式"
Python提供了多种文件打开模式,就像不同的读书方式:
| 模式 | 描述 | 例子 |
|---|---|---|
'r' | 只读模式(默认) | open("file.txt", "r") |
'w' | 写入模式(会覆盖原有内容) | open("file.txt", "w") |
'a' | 追加模式(在文件末尾添加) | open("file.txt", "a") |
'x' | 创建新文件(如果文件已存在则报错) | open("new_file.txt", "x") |
'b' | 二进制模式 | open("image.jpg", "rb") |
't' | 文本模式(默认) | open("file.txt", "rt") |
'+' | 读写模式 | open("file.txt", "r+") |
四、文本文件操作:读写文字内容
4.1 读取文件内容
# 方法1:一次性读取整个文件
with open("story.txt", "r", encoding="utf-8") as file:
content = file.read()
print("整个故事:")
print(content)
# 方法2:逐行读取
with open("story.txt", "r", encoding="utf-8") as file:
print("逐行阅读:")
for line in file:
print(line.strip()) # strip() 去除行末的换行符
# 方法3:读取所有行到列表
with open("story.txt", "r", encoding="utf-8") as file:
lines = file.readlines()
print(f"故事共有 {len(lines)} 行")
for i, line in enumerate(lines, 1):
print(f"第{i}行: {line.strip()}")
4.2 写入文件内容
# 写入新文件(会覆盖原有内容)
with open("diary.txt", "w", encoding="utf-8") as file:
file.write("2023年10月27日\n")
file.write("今天学习了Python文件操作!\n")
file.write("感觉很棒!\n")
# 追加内容到文件末尾
with open("diary.txt", "a", encoding="utf-8") as file:
file.write("2023年10月28日\n")
file.write("今天要继续努力学习!\n")
# 写入多行内容
lines = ["第一行\n", "第二行\n", "第三行\n"]
with open("multiline.txt", "w", encoding="utf-8") as file:
file.writelines(lines)
五、使用with语句:自动关闭文件
重要:总是使用with语句来操作文件!它会自动关闭文件,即使发生异常也不会泄露资源。
# 不好的做法:需要手动关闭
file = open("test.txt", "r")
content = file.read()
file.close() # 容易忘记关闭!
# 好的做法:自动关闭
with open("test.txt", "r") as file:
content = file.read()
# 文件在这里自动关闭,即使发生异常也会关闭
六、文件路径:找到你要的文件
6.1 相对路径和绝对路径
import os
# 当前工作目录
print("当前工作目录:", os.getcwd())
# 相对路径(相对于当前目录)
with open("data.txt", "r") as file: # 当前目录下的data.txt
pass
with open("./data.txt", "r") as file: # 同上,./表示当前目录
pass
with open("../parent_data.txt", "r") as file: # 上级目录的文件
pass
with open("data/files/data.txt", "r") as file: # 当前目录的data子目录
pass
# 绝对路径(完整路径)
with open("/Users/username/documents/data.txt", "r") as file:
pass
6.2 路径操作(os.path模块)
import os
# 拼接路径
path = os.path.join("folder", "subfolder", "file.txt")
print("拼接后的路径:", path)
# 获取路径的各个部分
file_path = "/home/user/documents/report.txt"
print("目录名:", os.path.dirname(file_path))
print("文件名:", os.path.basename(file_path))
print("分割扩展名:", os.path.splitext(file_path))
# 检查路径是否存在
if os.path.exists("some_file.txt"):
print("文件存在")
else:
print("文件不存在")
# 检查是否是文件/目录
if os.path.isfile("some_file.txt"):
print("这是一个文件")
if os.path.isdir("some_folder"):
print("这是一个目录")
七、二进制文件操作:处理图片、视频等
# 读取二进制文件(如图片)
with open("photo.jpg", "rb") as file:
image_data = file.read()
print(f"图片大小: {len(image_data)} 字节")
# 写入二进制文件
with open("copy.jpg", "wb") as file:
file.write(image_data)
# 复制文件(二进制模式)
def copy_file(source, destination):
with open(source, "rb") as src_file:
with open(destination, "wb") as dest_file:
# 分块读取和写入,适合大文件
chunk_size = 4096 # 4KB的块
while True:
chunk = src_file.read(chunk_size)
if not chunk:
break
dest_file.write(chunk)
print(f"文件已从 {source} 复制到 {destination}")
copy_file("original.jpg", "backup.jpg")
八、CSV文件操作:处理表格数据
import csv
# 写入CSV文件
with open("students.csv", "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(["姓名", "年龄", "成绩"]) # 写入表头
writer.writerow(["张三", 20, 95])
writer.writerow(["李四", 21, 88])
writer.writerow(["王五", 19, 92])
# 读取CSV文件
with open("students.csv", "r", encoding="utf-8") as file:
reader = csv.reader(file)
print("学生信息:")
for row in reader:
print(f"姓名: {row[0]}, 年龄: {row[1]}, 成绩: {row[2]}")
# 使用字典方式读写CSV(更推荐)
with open("students_dict.csv", "w", newline="", encoding="utf-8") as file:
fieldnames = ["name", "age", "grade"]
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({"name": "张三", "age": 20, "grade": 95})
writer.writerow({"name": "李四", "age": 21, "grade": 88})
with open("students_dict.csv", "r", encoding="utf-8") as file:
reader = csv.DictReader(file)
for row in reader:
print(f"{row['name']}今年{row['age']}岁,成绩{row['grade']}分")
九、JSON文件操作:处理结构化数据
import json
# 准备数据
data = {
"name": "张三",
"age": 25,
"hobbies": ["读书", "编程", "游泳"],
"address": {
"city": "北京",
"street": "朝阳区"
}
}
# 写入JSON文件
with open("user.json", "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=2)
# 读取JSON文件
with open("user.json", "r", encoding="utf-8") as file:
loaded_data = json.load(file)
print("用户信息:")
print(f"姓名: {loaded_data['name']}")
print(f"年龄: {loaded_data['age']}")
print(f"爱好: {', '.join(loaded_data['hobbies'])}")
print(f"城市: {loaded_data['address']['city']}")
# JSON字符串与Python对象的转换
json_str = json.dumps(data, ensure_ascii=False) # 对象转JSON字符串
print("JSON字符串:", json_str)
new_data = json.loads(json_str) # JSON字符串转对象
print("解析后的数据:", new_data)
十、文件管理和操作
import os
import shutil
# 创建目录
os.makedirs("my_folder/sub_folder", exist_ok=True)
# 重命名文件
if os.path.exists("old_name.txt"):
os.rename("old_name.txt", "new_name.txt")
# 删除文件
if os.path.exists("file_to_delete.txt"):
os.remove("file_to_delete.txt")
# 删除空目录
if os.path.exists("empty_folder"):
os.rmdir("empty_folder")
# 删除非空目录
if os.path.exists("folder_with_files"):
shutil.rmtree("folder_with_files")
# 遍历目录
print("当前目录内容:")
for item in os.listdir("."):
item_path = os.path.join(".", item)
if os.path.isfile(item_path):
print(f"文件: {item}")
elif os.path.isdir(item_path):
print(f"目录: {item}")
# 递归遍历所有文件和子目录
for root, dirs, files in os.walk("."):
print(f"当前目录: {root}")
print(f"子目录: {dirs}")
print(f"文件: {files}")
print("-" * 30)
十一、异常处理:文件操作中的错误处理
import os
def safe_file_operation(filename, mode="r"):
try:
with open(filename, mode, encoding="utf-8") as file:
if mode == "r":
return file.read()
elif mode == "w":
file.write("测试内容")
return "写入成功"
except FileNotFoundError:
return f"错误: 找不到文件 {filename}"
except PermissionError:
return f"错误: 没有权限访问 {filename}"
except IsADirectoryError:
return f"错误: {filename} 是一个目录"
except UnicodeDecodeError:
return f"错误: 文件编码问题"
except Exception as e:
return f"未知错误: {e}"
# 测试各种情况
print(safe_file_operation("不存在.txt")) # 文件不存在
print(safe_file_operation("/root/secret.txt")) # 权限不足
print(safe_file_operation("my_folder")) # 是目录不是文件
print(safe_file_operation("valid_file.txt", "w")) # 正常操作
十二、实战项目:个人日记本程序
让我们用文件操作创建一个完整的日记本程序:
import os
import json
from datetime import datetime
class Diary:
def __init__(self, diary_folder="my_diary"):
self.diary_folder = diary_folder
os.makedirs(diary_folder, exist_ok=True)
def write_entry(self, content):
"""写日记"""
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
filename = f"{timestamp}.txt"
filepath = os.path.join(self.diary_folder, filename)
try:
with open(filepath, "w", encoding="utf-8") as file:
file.write(f"时间: {datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')}\n")
file.write("=" * 50 + "\n")
file.write(content + "\n")
print("日记保存成功!")
return True
except Exception as e:
print(f"保存失败: {e}")
return False
def list_entries(self):
"""列出所有日记"""
entries = []
for filename in os.listdir(self.diary_folder):
if filename.endswith(".txt"):
entries.append(filename)
if not entries:
print("还没有日记呢!")
return
print("\n我的日记:")
for i, filename in enumerate(sorted(entries), 1):
print(f"{i}. {filename[:-4]}") # 去掉.txt后缀
def read_entry(self, entry_number):
"""读取特定日记"""
entries = [f for f in os.listdir(self.diary_folder) if f.endswith(".txt")]
if not entries:
print("还没有日记呢!")
return
entries.sort()
try:
if 1 <= entry_number <= len(entries):
filename = entries[entry_number - 1]
filepath = os.path.join(self.diary_folder, filename)
with open(filepath, "r", encoding="utf-8") as file:
content = file.read()
print(f"\n{'-'*60}")
print(content)
print(f"{'-'*60}")
else:
print("无效的日记编号!")
except Exception as e:
print(f"读取失败: {e}")
def search_entries(self, keyword):
"""搜索包含关键词的日记"""
found_entries = []
for filename in os.listdir(self.diary_folder):
if filename.endswith(".txt"):
filepath = os.path.join(self.diary_folder, filename)
try:
with open(filepath, "r", encoding="utf-8") as file:
content = file.read()
if keyword.lower() in content.lower():
found_entries.append((filename, content))
except:
continue
if not found_entries:
print(f"没有找到包含 '{keyword}' 的日记")
return
print(f"\n找到 {len(found_entries)} 篇包含 '{keyword}' 的日记:")
for i, (filename, content) in enumerate(found_entries, 1):
print(f"{i}. {filename[:-4]}")
# 显示匹配的上下文
lines = content.split('\n')
for line in lines:
if keyword.lower() in line.lower():
print(f" → {line.strip()}")
print()
# 使用日记本
def main():
diary = Diary()
while True:
print("\n=== 我的个人日记本 ===")
print("1. 写新日记")
print("2. 查看日记列表")
print("3. 阅读日记")
print("4. 搜索日记")
print("5. 退出")
choice = input("请选择操作 (1-5): ")
if choice == "1":
print("\n开始写日记(输入完按Ctrl+D或Ctrl+Z结束):")
print("请输入日记内容:")
content = []
try:
while True:
line = input()
content.append(line)
except EOFError:
pass # 用户结束输入
diary.write_entry("\n".join(content))
elif choice == "2":
diary.list_entries()
elif choice == "3":
diary.list_entries()
try:
num = int(input("\n请输入要阅读的日记编号: "))
diary.read_entry(num)
except ValueError:
print("请输入有效的数字!")
elif choice == "4":
keyword = input("请输入要搜索的关键词: ")
diary.search_entries(keyword)
elif choice == "5":
print("再见!")
break
else:
print("无效的选择,请重新输入!")
if __name__ == "__main__":
main()
十三、高级技巧:文件压缩和序列化
import zipfile
import pickle
# 创建ZIP压缩文件
with zipfile.ZipFile('archive.zip', 'w') as zipf:
zipf.write('file1.txt')
zipf.write('file2.txt')
print("文件已压缩")
# 解压ZIP文件
with zipfile.ZipFile('archive.zip', 'r') as zipf:
zipf.extractall('extracted_files')
print("文件已解压")
# 使用pickle序列化Python对象
data = {"name": "张三", "scores": [90, 85, 95], "active": True}
# 序列化到文件
with open('data.pkl', 'wb') as f:
pickle.dump(data, f)
# 从文件反序列化
with open('data.pkl', 'rb') as f:
loaded_data = pickle.load(f)
print("加载的数据:", loaded_data)
十四、总结:文件操作的核心要点
- 总是使用with语句:自动处理文件关闭
- 指定正确的编码:特别是处理中文时使用
utf-8 - 处理异常:文件操作容易出错,要做好错误处理
- 选择正确的模式:根据需求选择读、写、追加等模式
- 管理文件路径:使用
os.path处理路径问题
十五、练习题
- 修改日记本程序,添加删除日记的功能
- 编写一个程序,统计一个文本文件中每个单词出现的次数
- 创建一个文件备份工具,能够备份指定目录的所有文件
- 编写一个程序,能够合并多个文本文件的内容
记住:文件操作是程序与外部世界沟通的桥梁,掌握了它,你的程序就拥有了"记忆"和"交流"的能力!现在,去创造能够持久保存数据的精彩程序吧!
5万+

被折叠的 条评论
为什么被折叠?



