文件操作
今日内容
-
字符编码
-
文件的概念
-
代码打开文件的两种方式
-
文件的读写模式
-
读取文件的模式
-
文件的诸多方式
-
文件内容修改
-
文件光标移动
-
计算机硬盘修改数据的原理(固态除外)
-
文件内容修改
字符编码
主要记录了人类的字符和数字的对应关系 人类的字符跟计算机所识别的二进制之间的对应关系。
- ASCII码
A-Z 65-90
a-z 97-122 - 常见的编码格式
GBK(中国)、shift_JIS(日本)、Euc_Kr(韩国)
Unicode、utf家族(utf8,utf16, utf32)
ps : 英文采用一个字节一个字母,中文字符采用三个字节或三个字节以上的表示一个字符
- 解决Python代码乱码的核心就是当初以什么编码存的就应该用什么编码取。
- 编码与解码
编码:人类字符 --- 计算机字符
encode()
解码:计算机字符 ---- 人类字符
decode()
ps: 在Python解释器中bytes类型可以看成二进制数据 一般出现的类型为 b' '
python 解释器的差异
在Python2中如果想打印汉字
文件头: #encoding:utf-8
字符串前面要加u

文件的概念
就是操作系统暴露给用户操作硬盘的快捷方式
eg 双击一个文件就是把硬盘里的数据加载到内存然后CPU再从内存里拿数据去执行。
Ctrl+S就是把内存里的文件加载到内存。
代码打开文件的两种方式

- 第一种
open() 第一参数传文件路径 第二个参数传打开文件的模式,第三个参数传打开文件的编码格式
然后在把open赋值给一个变量名。
在结束文件操作的时候需要自己手动去执行
close()方法去关闭文件
要不然会在后台占用资源
也不会占用过多 但当你的内存处于一个临界值的时候就不好办了

-
第二种
with open 传参数跟open一样 在open写完以后再后面as 一个变量名
这种方法的好处是不需要自己手动去写close
with内部会执行完内部代码的时候自动去运行close代码。
with支持一次性打开多个文件 在变量名之后写逗号 然后继续写open方法就行,但是一般同时打开两个或最多三个文件。 -
怎么传参数
-
open第一参数传路径
windows操作系统上路径的连接符是斜杠 会与Python的转义符冲突导致Python解释器读取路径失败所以在写路径的时候可以在路径前面加个r

Linux操作系统下不会因为Linux下是反斜杠

-
第二个参数传的是打开模式
一般有 r w a rt wt at rb wb ab
默认 r w a不写的情况下就是 rt wt at -
第三个参数就是编码格式
如果你不写第三个参数就会以计算机的默认的编码格式打开文件可能会造成乱码。
Windows默认的编码格式是gbkLinux默认的编码格式是utf8
-
文件的读写模式
-
r模式 (只读模式)
读文件如果路径下的文件不存在则报错。

报一个找不到文件的错误
-
w模式 (只写模式)
如果路径下有这个文件则先清空在写入,没有则创建。
执行前

执行后

-
a模式(追加模式)
如果路径下没有这个文件则创建,若有则从文件末尾追加数据。执行前

执行后

读取文件的模式
-
t模式(默认t模式)
- 只能读取文本
- 单位都是字符
- 需要传encoding参数

-
b 模式
- 可以读取任意的文件
- 单位是字节(bytes)
- 不需要传encoding参数

文件的方法
-
read()方法读取文件
也可以在括号里写整形设置读取多少个字符
发现第一次直接把里面的数据全部都读完了光标都移动到文件末尾了所以第二次什么也没读出来。
-
readline 每次读一行因为如果read是把全部文件直接读取到硬盘可能会内存溢出(也就是内存撑爆了)
所以就可以按行读去
for循环也是一行一行的读的

-
readlines 就是把文件每一行的数据装进一个列表里面

ps:每一行的末尾都有一个换行符 -
readable 是判断文件是否具备读数据的能力(返回的是一个布尔值)

-
write方法就是在文件里写数据
在w模式下多次使用write方法只会在上一次写数据的末尾后继续写数据
-
writelines 参数是一个列表把列表里的所有数据写入到文件里

-
writeable 判断文件是否有写数据的能力
返回的也是一个布尔值

因为我是以 r 模式打开的所以判断不可以写
-
flush方法就相当于Ctrl+s将内存中的数据立马刷入到硬盘。
光标的移动
seek需要传两个参数 都是整形 一个是 移动的位数(单位是字节)
另一个是模式
- 模式有三种 分别是
-
0模式
从文件的开头开始往右移动文本和二进制都可以使用
t 模式下

因为一个汉字三个字节所以
f.seek()只移动光标到了放字了后面b模式下

-
1从文件的当前位置往右移动 只有二进制可以使用
t模式直接报错

b模式

因为是r模式光标的默认位置在开头所以
seek()的0模式和1模式一样都是在开头往后移动3个字节 -
2从文件的末尾往右移动 只有二进制可以使用
t模式报错
b模式

因为
seek()的 2 模式是光标从文件末尾开始移动所以什么也没读出来
光标移动案例
执行前

执行后

而这种缺陷很大只有用代码写入文件的才能监测到直接往里面写检测不到
源码
import time
with open(r"a.txt", "rb") as f:
f.seek(0, 2)
while True:
line = f.read()
if len(line) == 0:
time.sleep(0.3)
else:
print(line.decode("utf8"))
计算机硬盘修改数据的原理(固态除外)

硬盘写数据可以看成是在硬盘上刻字 一旦需要修改中间的内容 则需要重新刻字
因为刻过的字不可能从中间再分开
硬盘删除数据的原理
不是直接删除而是改变状态 等待后续数据的覆盖才会被真正删除
不管是哪种硬盘,删除的本质其实都是覆盖。
详细了解(删除的底层原理)
https://baijiahao.baidu.com/s?id=1728977978098417021&wfr=spider&for=pc
文件内容修改
两种方式
方式一
-
执行前

-
执行后

方式二
-
执行前

-
执行后

就是在新的文件把新的内容数据进去,然后把原文件删除掉,把新文件的名字修改成原来文件的名称
作业
# 1.
# 编写简易版本的拷贝工具
# 自己输入想要拷贝的数据路径
# 自己输入拷贝到哪个地方的目标路径
# 任何类型数据皆可拷贝
# ps: 个别电脑C盘文件由于权限问题可能无法拷贝
# 换其他盘尝试即可
file_path = input("请输入您要复制的文件路径:").strip()
file_path1 = input("请输入目的文件路径:").strip()
with open(r"{}".format(file_path), "rb") as f, open(r"{}".format(file_path1), "wb") as f1:
for line in f:
f1.write(line)
print("执行完毕!")
# 2.
# 利用文件充当数据库编写用户登录、注册功能
# 文件名称: userinfo.txt
# 基础要求:
# 用户注册功能 >> >: 文件内添加用户数据(用户名、密码等)
# 用户登录功能 >> >: 读取文件内用户数据做校验
# ps: 上述功能只需要实现一次就算过关(单用户)
# 文件内始终就一个用户信息
# 拔高要求:
# 用户可以连续注册
# 用户可以多账号切换登录(多用户)
# 文件内有多个用户信息
# ps: 思考多用户数据情况下如何组织文件内数据结构较为简单
# 提示: 本质其实就是昨天作业的第二道题
# 只不过数据库由数据类型变成文件
import os
while True:
print("""
1.注册功能
2.登录功能
""")
choice = input("请输入功能编号:").strip()
if choice.lower() == "q":
break
if not choice.isdigit():
print("请输入数字,大傻子!数字")
continue
if choice == "1":
""" 注册功能"""
while True:
user_name = input("请输入用户名:").strip()
if user_name.lower() == "q":
break
if not os.path.exists("userinfo.txt"):
with open("userinfo.txt", "w", encoding="utf8") as f:
pass
with open("userinfo.txt", "r", encoding="utf8") as read_file:
for line in read_file:
name, pwd = line.split("|")
if user_name == name:
print("用户已存在!")
break
else:
with open("userinfo.txt", "a", encoding="utf8") as write_file:
user_pwd = input("请输入密码:").strip()
data = "{}|{}\n".format(user_name, user_pwd)
write_file.write(data)
print("注册成功")
elif choice == "2":
"""登录功能"""
while True:
user_name = input("请输入用户名:").strip()
if user_name.lower() == "q":
break
user_pwd = input("请输入密码:").strip()
with open("userinfo.txt", "r", encoding="utf")as read_file:
for line in read_file:
name, pwd = line.split("|")
if user_name == name and user_pwd == pwd.strip("\n"):
print("登陆成功!")
break
else:
print("密码或用户名错误!")
else:
print("抱歉其他功能待开发!")
continue

浙公网安备 33010602011771号