数据分析笔记14:Python文件操作
编码基础理论
为什么需要编码
计算机只能识别0和1,而人类使用文字、字母、符号。编码是将两者之间进行转换的机制。
编码流程:
人类语言(汉字/字母) → [编码] → 机器语言(0101)
机器语言(0101) → [解码] → 人类语言(汉字/字母)
核心原则:编码和解码必须使用同一套编码表。
常见编码表对比
| 编码类型 | 发明者 | 支持范围 | 特点 |
|---|---|---|---|
| ASCII | 美国 | 英文大小写、特殊字符 | 不支持中文 |
| GBK | 中国 | 中文、英文 | 支持中文 |
| GB2312 | 中国 | 简体中文 | 范围较小 |
| Unicode | 国际 | 全球语言 | 空间占用大 |
| UTF-8 | 国际 | 全球语言 | Python常用 |
编码实务操作
编码示例(GBK):
print("世界".encode("GBK"))
# 输出:b'\xca\xc0\xbd\xe7'
编码示例(UTF-8):
print("世界".encode("UTF-8"))
# 输出:b'\xe4\xb8\x96\xe7\x95\x8c'
解码示例:
# GBK解码
print(b'\xca\xc0\xbd\xe7'.decode("GBK"))
# 输出:世界
# UTF-8解码
print(b'\xe4\xb8\x96\xe7\x95\x8c'.decode("UTF-8"))
# 输出:世界
深度理解:\x 表示16进制格式。GBK用4个字节表示"世界",UTF-8用6个字节。
路径管理系统
绝对路径 vs 相对路径
绝对路径:从盘符根目录开始的完整路径。
r"D:\download\Python\test.py"
优点:
- 不受当前位置影响。
- 移动脚本后仍可正确找到文件。
- 推荐使用。
相对路径:以当前文件位置为参照。
"test.txt" # 同目录下的文件
缺点:
- 脚本移动后路径失效。
- 需要修改代码。
获取绝对路径的方法
在PyCharm中:
- 右键点击文件。
- Copy Path。
- 选择 Absolute Path。
文件读写核心机制
文件操作三步骤
- 打开文件:f = open("文件路径", "模式", encoding="UTF-8")。
- 读写操作:f.write("内容") 或 f.read()。
- 关闭文件:f.close()。
open()函数详解
语法结构:
open(file_name, mode, encoding)
参数说明:
- file_name:文件路径(含文件名)。
- mode:打开模式(见下表)。
- encoding:编码格式(推荐UTF-8)。
文件打开模式对比
| 模式 | 英文全称 | 功能 | 文件不存在时 | 文件存在时 |
|---|---|---|---|---|
| r | read | 只读 | 报错 | 读取内容 |
| w | write | 写入 | 创建新文件 | 覆盖旧内容 |
| a | append | 追加 | 创建新文件 | 在尾部追加内容 |
重要区别:w模式会完全覆盖旧内容,a模式会保留旧内容并在后面追加。
转义字符问题
问题:绝对路径中的反斜杠可能被误认为特殊字符。
# 错误:\b、\p、\d 可能被识别为特殊字符
"D:\python\test.py"
解决方案1:双反斜杠
"D:\\python\\test.py"
解决方案2:原始字符串(推荐)
r"D:\python\test.py" # 前面加 r
文件读取三大函数
read() - 一次性读取
特点:读取全部内容,返回字符串。
with open(r"路径", "r", encoding="UTF-8") as f:
content = f.read()
print(content) # 字符串格式
print(type(content)) # <class 'str'>
readlines() - 列表格式读取
特点:读取全部内容,返回列表(每行一个元素)。
with open(r"路径", "r", encoding="UTF-8") as f:
lines = f.readlines()
print(lines) # ['第一行\n', '第二行\n', '第三行']
print(type(lines)) # <class 'list'>
readline() - 逐行读取
特点:每次读取一行(单数形式)。
with open(r"路径", "r", encoding="UTF-8") as f:
line1 = f.readline() # 读取第1行
print(f"第一行:{line1}")
line2 = f.readline() # 读取第2行
print(f"第二行:{line2}")
函数对比表:
| 函数 | 返回类型 | 读取方式 | 适用场景 |
|---|---|---|---|
| read() | 字符串 | 一次全部 | 小文件 |
| readlines() | 列表 | 一次全部 | 需要遍历每行 |
| readline() | 字符串 | 逐行读取 | 大文件/逐行处理 |
with open 自动管理
为什么使用 with
传统方式的问题:
f = open("文件", "r")
content = f.read()
f.close() # 容易忘记关闭
with方式的优势:
with open("文件", "r", encoding="UTF-8") as fp:
content = fp.read()
# 自动关闭,无需 fp.close()
语法结构
with open(文件路径, 模式, encoding=编码) as 变量名:
# 文件操作
变量名.read() / 变量名.write()
# 代码块结束后自动关闭文件
最佳实践:后续所有文件操作统一使用 with open 方式。
文件写入与追加
创建不同类型文件
关键:通过后缀名区分文件类型。
# 创建CSV文件
with open("output_file.csv", "w", encoding="UTF-8") as f:
f.write("Hello Universe")
# 创建TXT文件
with open("output_file.txt", "w", encoding="UTF-8") as f:
f.write("测试内容")
# 创建Excel文件
with open("output_file.xlsx", "w", encoding="UTF-8") as f:
f.write("数据")
写入与追加示例
覆盖写入(w模式):
with open(r"路径\test.txt", "w", encoding="UTF-8") as f:
f.write("这是测试的文件相对路径")
# 旧内容被完全覆盖
追加写入(a模式):
with open(r"路径\test.txt", "a", encoding="UTF-8") as f:
f.write("\n") # 先换行
f.write("这是测试文件绝对路径")
# 旧内容保留,新内容追加在后
用户登录验证系统
需求分析
功能:
- 从 user.txt 读取预存的用户名和密码。
- 用户输入账号密码。
- 验证成功 → 显示"登录成功"并退出。
- 验证失败 → 显示"用户名或密码错误"并重新输入。
user.txt 文件格式:
用户一:pass123
用户二:456
test_user:password
完整代码实现
def 用户登录验证系统():
while True:
# 步骤1:获取用户输入
name = input("请输入用户名:").strip()
pwd = input("请输入密码:").strip()
# 步骤2:读取文件中的账号数据
with open(r"绝对路径\user.txt", "r", encoding="UTF-8") as file:
info = file.readlines()
print(info) # 调试用
# 步骤3:遍历每行数据进行验证
for line in info:
# 清除换行符并按冒号分割
u_name, u_pwd = line.strip("\n").split(":")
# 步骤4:验证账号密码
if u_name == name and u_pwd == pwd:
print("登录成功")
return # 结束函数
# 步骤5:所有账号都不匹配
else:
print("用户名或密码错误")
# 调用函数
用户登录验证系统()
代码深度解析
关键技术点1:数据清洗
line.strip("\n") # 去除行尾的换行符
关键技术点2:字符串分割
u_name, u_pwd = "用户一:pass123".split(":")
# u_name = "用户一"
# u_pwd = "pass123"
关键技术点3:序列赋值
# split()返回列表:["用户一", "pass123"]
# 自动按位置赋值给两个变量
u_name, u_pwd = ["用户一", "pass123"]
关键技术点4:for...else结构
for line in info:
if 条件成立:
return # 找到匹配,退出
else:
# 遍历完所有数据都不匹配时执行
print("用户名或密码错误")
名片管理系统的痛点
- 数据存储在临时内存(列表)。
- 程序关闭后数据全部丢失。
- 无法实现数据持久化。
文件存储的优势
- 数据存储在硬盘文件。
- 程序关闭后数据永久保存。
- 下次启动直接读取历史数据到内存。
升级思路
添加名片时:
def add_card():
# 原有逻辑:收集姓名、电话、微信、邮箱
card = {...}
card_list.append(card)
# 新增:写入文件
with open("cards.txt", "a", encoding="UTF-8") as f:
f.write(f"{card}\n")
启动程序时:
def load_cards():
with open("cards.txt", "r", encoding="UTF-8") as f:
# 读取并恢复数据到 card_list
pass
常见错误防范
| 错误类型 | 原因 | 解决方案 |
|---|---|---|
| UnicodeDecodeError | 编码不匹配 | 指定正确的encoding |
| FileNotFoundError | 路径错误 | 使用绝对路径 + 检查文件是否存在 |
| 特殊字符问题 | 转义字符冲突 | 路径前加 r |
| 文件未关闭 | 忘记close() | 使用 with open |