python系列之文件操作:让程序拥有“记忆“的超能力!

不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。

python系列前期章节

  1. python系列之注释与变量
  2. python系列之输入输出语句与数据类型
  3. python系列之运算符
  4. python系列之控制流程语句
  5. python系列之字符串
  6. python系列之列表
  7. python系列之元组
  8. python系列之字典
  9. python系列之集合
  10. python系列之函数基础
  11. python系列之函数进阶
  12. python系统之综合案例1:用python打造智能诗词生成助手
  13. python系列之综合案例2:用python开发《魔法学院入学考试》文字冒险游戏
  14. python系列之类与对象:面向对象编程(用造人计划秒懂面向对象)
  15. python系列之类与对象:python系列之详解面向对象的属性)
  16. python系列之详解面向对象的函数
  17. python系列之面向对象的三大特性
  18. python系列之异常处理:给代码穿上“防弹衣”

阅读建议:想象自己是一名数据魔法师,正在学习如何读取、写入和操控信息的奥秘!📁✨

一、前言:为什么需要文件操作?

想象一下:你写了一个很棒的程序,但每次关闭后,所有数据都消失了。就像用粉笔在黑板上写字,一擦就没了!

文件操作让程序能够:

  • 📝 保存数据:游戏进度、用户设置、计算结果
  • 📖 读取数据:配置文件、数据库、日志文件
  • 🔄 交换数据:与其他程序共享信息

二、文件操作的基本步骤:打开→操作→关闭

文件操作就像读书一样简单:

  1. 打开书(打开文件)
  2. 读书或写字(读取或写入)
  3. 合上书(关闭文件)
# 基本文件操作流程
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)

十四、总结:文件操作的核心要点

  1. 总是使用with语句:自动处理文件关闭
  2. 指定正确的编码:特别是处理中文时使用utf-8
  3. 处理异常:文件操作容易出错,要做好错误处理
  4. 选择正确的模式:根据需求选择读、写、追加等模式
  5. 管理文件路径:使用os.path处理路径问题

十五、练习题

  1. 修改日记本程序,添加删除日记的功能
  2. 编写一个程序,统计一个文本文件中每个单词出现的次数
  3. 创建一个文件备份工具,能够备份指定目录的所有文件
  4. 编写一个程序,能够合并多个文本文件的内容

记住:文件操作是程序与外部世界沟通的桥梁,掌握了它,你的程序就拥有了"记忆"和"交流"的能力!现在,去创造能够持久保存数据的精彩程序吧!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值