目录
一、文件基础概念
1.1 什么是文件?
在计算机中,文件是指存储在某种长期储存设备上的一段数据。这些长期存储设备包括:
-
硬盘(HDD/SSD)
-
U盘和移动硬盘
-
光盘(CD/DVD)
-
网络存储设备
文件的核心作用是将数据长期保存下来,在需要时可以随时访问和使用。与内存中的临时数据不同,文件中的数据在计算机关闭后仍然能够保留。
1.2 文件的存储方式
所有计算机文件都是以二进制形式存储在磁盘上的。根据内容和用途的不同,文件可以分为两大类:
文本文件
-
特点:由可打印字符组成,人类可直接阅读
-
查看方式:可以使用文本编辑软件(如记事本、VS Code等)查看
-
本质:仍然是二进制文件,只是遵循特定编码规则
-
示例:Python源程序(.py)、HTML文件(.html)、Markdown文件(.md)
二进制文件
-
特点:内容不是为直接阅读设计的,而是供特定软件使用
-
查看方式:需要专用软件才能正确解析
-
示例:图片(.jpg, .png)、音频(.mp3)、视频(.mp4)、可执行程序(.exe)
二、Python文件操作基础
2.1 文件操作三步曲
在Python中操作文件遵循固定的三个步骤:
-
打开文件:建立程序与文件的连接
-
读写操作:
-
读取:将文件内容加载到内存
-
写入:将内存中的数据保存到文件
-
-
关闭文件:释放系统资源
2.2 核心函数与方法
Python提供了以下关键函数和方法来进行文件操作:
序号 | 函数/方法 | 说明 | 使用示例 |
---|---|---|---|
01 | open() | 打开文件并返回文件对象 | file = open("test.txt") |
02 | read() | 读取文件全部内容 | content = file.read() |
03 | write() | 写入内容到文件 | file.write("Hello") |
04 | close() | 关闭文件 | file.close() |
重要提示:
-
open()
函数返回的文件对象是后续所有操作的基础 -
操作完成后必须调用
close()
释放资源,否则可能导致:-
系统资源浪费
-
文件被占用无法被其他程序访问
-
数据未完全写入磁盘
-
2.3 文件读取详解
基本读取示例
# 1. 打开文件(注意文件名大小写敏感)
file = open("example.txt")
# 2. 读取内容
content = file.read()
print(content)
# 3. 关闭文件
file.close()
文件指针机制
-
文件指针标记当前读取位置
-
初次打开时,指针位于文件开头
-
执行
read()
后,指针移动到文件末尾 -
再次调用
read()
将无法读取内容(因为指针已在末尾)
开发建议:先编写打开/关闭代码框架,再填充中间的读写逻辑,避免忘记关闭文件。
2.4 文件打开模式
open()
函数的第二个参数指定文件打开模式:
模式 | 说明 | 文件存在时 | 文件不存在时 |
---|---|---|---|
r | 只读 | 指针在开头 | 抛出异常 |
w | 只写 | 内容被清空 | 创建新文件 |
a | 追加 | 指针在末尾 | 创建新文件 |
r+ | 读写 | 指针在开头 | 抛出异常 |
w+ | 读写 | 内容被清空 | 创建新文件 |
a+ | 读写 | 指针在末尾 | 创建新文件 |
性能提示:频繁移动文件指针会影响性能,多数情况下使用简单的只读(r)或只写(w)模式即可。
写入文件示例
# 以写入模式打开文件(会覆盖原有内容)
f = open("diary.txt", "w")
f.write("2023年5月15日\n")
f.write("今天学习了Python文件操作\n")
f.write("收获很大!")
f.close() # 确保内容被写入磁盘
2.5 高效读取大文件
read()
方法会一次性加载全部内容,对于大文件可能导致内存不足。解决方案是使用readline()
逐行读取:
file = open("large_log.txt")
while True:
line = file.readline()
# 读到空字符串表示文件结束
if not line:
break
# 每行末尾已有\n,所以print不需要换行
print(line, end="")
file.close()
优化技巧:对于超大型文件,还可以考虑使用固定大小的缓冲读取:
with open("huge_file.bin", "rb") as f:
while chunk := f.read(4096): # 每次读取4KB
process(chunk)
三、文件操作实战案例
3.1 文件复制功能实现
小文件复制(一次性读写)
# 源文件和目标文件
source = "document.pdf"
target = "document_backup.pdf"
# 使用二进制模式确保所有文件都能正确复制
with open(source, "rb") as src, open(target, "wb") as dst:
content = src.read()
dst.write(content)
大文件复制(逐块读写)
def copy_large_file(src_path, dst_path, buffer_size=1024*1024):
"""复制大文件,默认使用1MB的缓冲区"""
with open(src_path, "rb") as src, open(dst_path, "wb") as dst:
while True:
chunk = src.read(buffer_size)
if not chunk:
break
dst.write(chunk)
# 使用示例
copy_large_file("big_video.mp4", "backup.mp4")
3.2 文件内容统计
def file_stats(filename):
"""统计文件的行数、单词数和字符数"""
lines = words = chars = 0
with open(filename, "r", encoding="utf-8") as f:
for line in f:
lines += 1
words += len(line.split())
chars += len(line)
return {"lines": lines, "words": words, "chars": chars}
# 使用示例
stats = file_stats("article.txt")
print(f"行数: {stats['lines']}, 单词数: {stats['words']}, 字符数: {stats['chars']}")
四、文件与目录管理
Python通过os
模块提供丰富的文件/目录管理功能:
4.1 文件操作
操作 | 方法 | 示例 | 注意事项 |
---|---|---|---|
重命名 | os.rename() | os.rename("old.txt", "new.txt") | 跨设备移动可能失败 |
删除 | os.remove() | os.remove("temp.txt") | 删除前应检查文件是否存在 |
存在检查 | os.path.exists() | os.path.exists("data.db") | 也可用于目录检查 |
4.2 目录操作
操作 | 方法 | 示例 | 说明 |
---|---|---|---|
列出内容 | os.listdir() | files = os.listdir(".") | 返回文件名列表 |
创建目录 | os.mkdir() | os.mkdir("new_folder") | 父目录必须存在 |
递归创建 | os.makedirs() | os.makedirs("path/to/folder") | 自动创建中间目录 |
删除目录 | os.rmdir() | os.rmdir("empty_dir") | 目录必须为空 |
获取当前目录 | os.getcwd() | print(os.getcwd()) | 返回绝对路径 |
切换目录 | os.chdir() | os.chdir("../") | 相对/绝对路径均可 |
4.3 路径操作最佳实践
建议使用os.path
模块处理路径相关问题:
import os
# 拼接路径(自动处理不同操作系统的分隔符)
config_path = os.path.join("config", "app", "settings.ini")
# 获取文件名和扩展名
filename = os.path.basename("/path/to/file.txt") # "file.txt"
file_ext = os.path.splitext(filename)[1] # ".txt"
# 路径存在性检查
if os.path.isfile(config_path):
print("配置文件存在")
五、文本编码深度解析
5.1 常见编码格式
-
ASCII:
-
最早的标准编码
-
仅包含128个字符(英文字母、数字、基本符号)
-
每个字符占1字节
-
-
Unicode:
-
涵盖全球所有文字系统
-
为每个字符分配唯一编码(码点)
-
UTF-8是最流行的Unicode实现方式
-
-
UTF-8:
-
变长编码(1-4字节)
-
英文1字节,中文通常3字节
-
兼容ASCII
-
5.2 Python编码处理
-
Python 3.x默认使用UTF-8编码
-
最佳实践:始终明确指定编码
# 推荐的文件打开方式
with open("multilang.txt", "r", encoding="utf-8") as f:
content = f.read()
5.3 编码问题排查
常见错误及解决方案:
-
UnicodeDecodeError:
-
原因:使用了错误的编码读取文件
-
解决方案:尝试其他编码(如gbk、utf-16)
-
try:
with open("unknown.txt", "r", encoding="utf-8") as f:
content = f.read()
except UnicodeDecodeError:
# 尝试其他编码
with open("unknown.txt", "r", encoding="gbk") as f:
content = f.read()
-
BOM头问题:
-
某些编辑器会在UTF-8文件开头添加BOM标记
-
解决方案:使用
encoding="utf-8-sig"
-
六、高级文件操作技巧
6.1 上下文管理器(with语句)
自动管理文件资源的推荐方式:
with open("data.txt", "r") as f:
content = f.read()
# 离开with块后文件会自动关闭,即使发生异常
6.2 二进制文件操作
处理图片、视频等二进制文件:
# 复制图片
with open("photo.jpg", "rb") as src, open("copy.jpg", "wb") as dst:
dst.write(src.read())
# 修改二进制文件特定位置
with open("data.bin", "r+b") as f:
f.seek(10) # 移动到第10字节
f.write(b"\x00") # 写入新值
6.3 临时文件处理
使用tempfile
模块创建临时文件:
import tempfile
# 创建临时文件(自动删除)
with tempfile.NamedTemporaryFile(delete=True) as tmp:
tmp.write(b"临时数据")
tmp.seek(0)
print(tmp.read())
6.4 文件压缩处理
使用标准库处理zip文件:
import zipfile
# 创建zip压缩包
with zipfile.ZipFile("archive.zip", "w") as zf:
zf.write("document.txt")
# 解压zip文件
with zipfile.ZipFile("archive.zip", "r") as zf:
zf.extractall("output_dir")
七、最佳实践总结
-
资源管理:
-
始终使用
with
语句确保文件正确关闭 -
避免同时打开过多文件
-
-
路径处理:
-
使用
os.path
代替手动拼接路径 -
处理用户输入路径时进行规范化
-
-
编码规范:
-
明确指定文件编码(推荐UTF-8)
-
处理多语言内容时考虑使用
chardet
检测编码
-
-
异常处理:
-
捕获文件操作可能抛出的异常(如FileNotFoundError)
-
提供有意义的错误信息
-
-
性能优化:
-
大文件使用流式处理(逐行或分块)
-
频繁的小文件操作考虑使用缓冲
-
八、常见问题解答
Q1:为什么我的文件内容没有被立即写入磁盘?
A:写入操作可能被缓冲,调用flush()
或关闭文件可强制写入。使用with
语句可自动处理。
Q2:如何同时读写同一个文件?
A:使用r+
模式,注意指针位置:
with open("data.txt", "r+") as f:
content = f.read()
f.seek(0)
f.write("New header\n" + content)
Q3:为什么读取中文文件会出现乱码?
A:因为使用了错误的编码打开文件,确保指定正确的编码(如encoding="utf-8"
)。
Q4:如何安全地修改文件内容?
A:推荐做法是:
-
读取原文件内容
-
在内存中修改
-
写入新文件
-
用新文件替换原文件
import os
def safe_update(filename, update_func):
"""安全更新文件内容"""
tempname = filename + ".tmp"
with open(filename, "r") as src, open(tempname, "w") as dst:
new_content = update_func(src.read())
dst.write(new_content)
os.replace(tempname, filename)