如何处理文件?
Python 提供了丰富的文件操作功能,支持文本文件、二进制文件、JSON、CSV 等多种格式。
0x01. 基本文件操作
使用内置函数 open() 来读取一个文件,open函数会返回一个fileObject对象。
打开文件
# 以文本模式打开文件(默认)
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
# 以二进制模式打开文件
with open('image.png', 'rb') as f:
binary_data = f.read()
# 打开模式说明
# 'r' - 只读(默认)
# 'w' - 写入(覆盖)
# 'a' - 追加
# 'x' - 独占创建
# 'b' - 二进制模式
# 't' - 文本模式(默认)
# '+' - 读写模式
读取文件
# 读取整个文件
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)
# 逐行读取
with open('file.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line.strip()) # strip() 去除换行符
# 读取所有行到列表
with open('file.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
print(lines) # ['line1\n', 'line2\n', 'line3\n']
# 读取一行
with open('file.txt', 'r', encoding='utf-8') as f:
line = f.readline()
print(line)
写入文件
# 写入文本
with open('output.txt', 'w', encoding='utf-8') as f:
f.write('Hello, World!\n')
f.write('第二行\n')
# 写入多行
lines = ['第一行\n', '第二行\n', '第三行\n']
with open('output.txt', 'w', encoding='utf-8') as f:
f.writelines(lines)
# 追加模式
with open('output.txt', 'a', encoding='utf-8') as f:
f.write('追加的内容\n')
文件指针操作
# tell() - 获取当前位置
with open('file.txt', 'r') as f:
print(f.tell()) # 0
f.read(10)
print(f.tell()) # 10
# seek() - 移动指针
with open('file.txt', 'r') as f:
f.seek(0) # 移动到开头
f.seek(10) # 移动到第10个字节
f.seek(0, 2) # 移动到文件末尾
0x02. os.path 模块
import os.path
# 路径操作
path = '/home/user/documents/file.txt'
print(os.path.abspath('file.txt')) # 获取绝对路径
print(os.path.basename(path)) # 'file.txt'
print(os.path.dirname(path)) # '/home/user/documents'
print(os.path.splitext(path)) # ('/home/user/documents/file', '.txt')
print(os.path.join('/home', 'user', 'file.txt')) # '/home/user/file.txt'
# 路径判断
print(os.path.exists(path)) # 判断是否存在
print(os.path.isfile(path)) # 判断是否是文件
print(os.path.isdir(path)) # 判断是否是目录
print(os.path.isabs(path)) # 判断是否是绝对路径
# 获取文件信息
print(os.path.getsize(path)) # 获取文件大小(字节)
print(os.path.getmtime(path)) # 获取修改时间
0x03. os 模块
import os
# 目录操作
os.getcwd() # 获取当前工作目录
os.chdir('/path/to/dir') # 改变当前目录
os.listdir('.') # 列出目录内容
os.mkdir('new_dir') # 创建目录
os.makedirs('a/b/c') # 递归创建目录
os.rmdir('dir') # 删除空目录
os.removedirs('a/b/c') # 递归删除空目录
# 文件操作
os.rename('old.txt', 'new.txt') # 重命名
os.remove('file.txt') # 删除文件
# 遍历目录
for root, dirs, files in os.walk('.'):
for file in files:
print(os.path.join(root, file))
# 环境变量
print(os.environ.get('HOME'))
os.environ['MY_VAR'] = 'value'
0x04. pathlib 模块(Python 3.4+)
from pathlib import Path
# 创建路径对象
p = Path('.')
p = Path('/home/user/documents')
p = Path('file.txt')
# 路径操作
print(p.name) # 文件名
print(p.stem) # 文件名(不含扩展名)
print(p.suffix) # 扩展名
print(p.parent) # 父目录
print(p.parents) # 所有父目录
print(p.absolute()) # 绝对路径
# 路径拼接
p = Path('/home') / 'user' / 'file.txt'
print(p) # /home/user/file.txt
# 路径判断
print(p.exists()) # 是否存在
print(p.is_file()) # 是否是文件
print(p.is_dir()) # 是否是目录
# 文件操作
p.read_text(encoding='utf-8') # 读取文本
p.read_bytes() # 读取二进制
p.write_text('Hello') # 写入文本
p.write_bytes(b'binary data') # 写入二进制
# 目录操作
Path('new_dir').mkdir(exist_ok=True) # 创建目录
Path('new_dir').mkdir(parents=True, exist_ok=True) # 递归创建
# 遍历目录
for file in Path('.').rglob('*.py'): # 递归查找所有 .py 文件
print(file)
for file in Path('.').iterdir(): # 列出目录内容
print(file)
0x05. JSON 文件处理
import json
# 写入 JSON
data = {
'name': 'Alice',
'age': 25,
'scores': [85, 90, 78],
'address': {
'city': 'Beijing',
'zip': '100000'
}
}
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# 读取 JSON
with open('data.json', 'r', encoding='utf-8') as f:
loaded_data = json.load(f)
print(loaded_data)
# JSON 字符串转换
json_str = json.dumps(data, indent=2, ensure_ascii=False)
print(json_str)
parsed = json.loads(json_str)
print(parsed)
0x06. CSV 文件处理
import csv
# 写入 CSV
data = [
['Name', 'Age', 'City'],
['Alice', 25, 'Beijing'],
['Bob', 30, 'Shanghai'],
['Charlie', 35, 'Guangzhou']
]
with open('data.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerows(data)
# 读取 CSV
with open('data.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row)
# 使用 DictReader/DictWriter
with open('data.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
print(row['Name'], row['Age'])
0x07. YAML 文件处理
# 需要安装 PyYAML: pip install pyyaml
import yaml
# 写入 YAML
data = {
'database': {
'host': 'localhost',
'port': 5432,
'name': 'mydb'
},
'users': ['alice', 'bob', 'charlie']
}
with open('config.yaml', 'w', encoding='utf-8') as f:
yaml.dump(data, f, default_flow_style=False)
# 读取 YAML
with open('config.yaml', 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
print(config)
0x08. 临时文件
import tempfile
import os
# 创建临时文件
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
f.write('临时数据')
temp_path = f.name
# 使用后删除
os.unlink(temp_path)
# 创建临时目录
with tempfile.TemporaryDirectory() as temp_dir:
# 在临时目录中操作
temp_file = os.path.join(temp_dir, 'test.txt')
with open(temp_file, 'w') as f:
f.write('测试')
# 退出 with 块后自动删除
# 获取系统临时目录
print(tempfile.gettempdir())
0x09. 文件编码检测
# 使用 chardet 检测编码
# pip install chardet
import chardet
with open('unknown_encoding.txt', 'rb') as f:
raw_data = f.read()
result = chardet.detect(raw_data)
print(result) # {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
# 使用检测到的编码读取
encoding = result['encoding']
text = raw_data.decode(encoding)
0x0A. 压缩文件处理
import zipfile
import tarfile
# ZIP 文件
# 创建 ZIP
with zipfile.ZipFile('archive.zip', 'w') as zf:
zf.write('file1.txt')
zf.write('file2.txt')
# 读取 ZIP
with zipfile.ZipFile('archive.zip', 'r') as zf:
print(zf.namelist()) # 列出文件
zf.extractall('output_dir') # 解压所有文件
content = zf.read('file1.txt') # 读取特定文件
# TAR 文件
# 创建 TAR
with tarfile.open('archive.tar.gz', 'w:gz') as tf:
tf.add('file1.txt')
tf.add('directory')
# 读取 TAR
with tarfile.open('archive.tar.gz', 'r:gz') as tf:
tf.extractall('output_dir')
参考
目录