今日内容:
1.字符编码: 人识别的语言与机器识别的语言转化的媒介 *****
2.字符与字节: 字符占多少字节,字符串转化 ***
3.文件操作: 操作硬盘中的一块区域:读写操作 *****
一、文本编辑器存取文件的原理
1、打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的内容也都是存放与内存中的,断电后数据丢失
2、要想永久保存,需要点击保存按钮:编辑器把内存的数据刷到了硬盘上。
3、在我们编写一个py文件(没有执行),跟编写其他文件没有任何区别,都只是在编写一堆字符而已
二、python解释器执行py文件的原理
第一阶段:python解释器启动,此时就相当于启动了一个文本编辑器
第二阶段:python解释器相当于文本编辑器,去打开test.py文件,从硬盘上将test.py的文件内容读入到内存中(小复习:pyhon的解释性,决定了解释器只关心文件内容,不关心文件后缀名)
第三阶段:python解释器解释执行刚刚加载到内存中test.py的代码( ps:在该阶段,即真正执行代码时,才会识别python的语法,执行文件内代码,当执行到name="egon"时,会开辟内存空间存放字符串"egon")
python解释器与文本编辑器的异同:
1、相同点:python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样
2、不同点:文本编辑器将文件内容读入内存后,是为了显示或者编辑,根本不去理会python的语法,而python解释器将文件内容读入内存后,可不是为了给你瞅一眼python代码写的啥,而是为了执行python代码、会识别python语法
三、字符编码
重点:什么是字符编码
人类能识别的是字符等高级标识符,电脑只能识别0,1组成的标识符,要完成人与机器之间的信息交流,
一定需要一个媒介,进行两种标识符的转化(两种标识符的对应关系)
对应关系形成的结构称之为:编码表
了解:编码表的发展史
1. ascii(ASCII):字母、数字、英文符号与计算机01标识符的对应关系
思考:如何将128个字符用01完全标签
二进制:11111111 => 255 => 1bytes(1字节) => 8个二进制位
2.中国:研究汉字与计算机01标识符的对应关系:gb2312 => GBK(***) => GB18030
日本:Shift_JIS
棒子:Euc-kr
3. 制造一个可以完成万国字符与计算机01标识符的对应关系的编码表
编码表:unicode表
py2:ascii,没有按万国编码,原因py2先于万国编码而诞生
py3: utf-8, 采用万国编码来解释文本内容
思考:unicode与utf-8是什么关系?
unicode:用2个字节来存储汉字,用2个字节来存储英文字母,占有空间较多,读取效率极高
utf-8:用3-6个字节来存储汉字,用1个字节来存储英文字母,占有空间较少,读取效率低
总结:内存都是按unicode存储数据,硬盘和cpu采用utf-8来存取数据
unicode与utf-8采用的是一张unicode编码表,utf-8是unicode编码表的体现方式,变长存储数据
变长优点:(大量数据都是以英文存在,所以utf-8空间更小)传输速度更快
四、三种字符串
# unicode字符串,默认字符串
s1 = u'abc你好\n不好'
print(s1)
# 字节字符串
s2 = b'abc123\xb7\xb7'
print(s2)
# 原义字符串: 不对字符串内部做任何操作(eg:\n的转化)
s3 = r'abc你好\n不好'
print(s3)
# 编码与解码
s = '123呵呵'
n_b = bytes(s, encoding='utf-8')
print(n_b)
b = b'123\xe5\x91\xb5\xe5\x91\xb5'
n_s = str(b, encoding='GBK')
print(n_s)
# 重点:*****
# 将u字符串编码成b字符串
print(u'你好'.encode('utf-8'))
# 将b字符串解码成u字符串
print(b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf-8'))
二进制字符串:用来传输的字符串
1. 是字符串(文本字符)的二进制体现,(如视频资源可以转化为二进制字符串,不翻转为视频资源,则就是普通字符串)
2. 二进制字符串按字节为最小存储单位存放数据
3. 所有数据转化为二进制字符串都应该用utf-8进行编码吗?
-- 只是文本数据
-- 视频、音频、图像等此类数据也有编码解码过程,采用的编码表不是utf-8,不用关系编码表
五、文件操作
文件:硬盘中一块存储空间(虚拟的文件)
文件操作:根据文件名来操作硬盘的某块存储空间,操作方式 :读read 写write
1、使用文件的三步骤:
# 1、打开文件,得到文件句柄并赋值给一个变量
变量名 = 文件空间
# 文件路径 操作模式(读|写) 编码
f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r
# 2、通过句柄对文件进行操作
data=f.read()
# 3、关闭文件
f.close()
# f=open('a.txt','r')的过程分析
1、由应用程序向操作系统发起系统调用open(...)
2、操作系统打开该文件,并返回一个文件句柄给应用程序
3、应用程序将文件句柄赋值给变量f
#强调第一点:
打开一个文件包含两部分资源:操作系统级打开的文件+应用程序的变量。在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:
1、f.close() #回收操作系统级打开的文件
2、del f #回收应用程序级的变量
其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件还没有关闭,白白占用资源,
而python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们,在操作完毕文件后,一定要记住f.close()
#强调第二点:
f=open(...)是由操作系统打开文件,那么我们一定要为open指定编码为utf-8
2、打开文件的模式
#1. 打开文件的模式有(默认为文本模式):
r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
w,只写模式【不可读;不存在则创建;存在则清空内容】
a, 之追加写模式【不可读;不存在则创建;存在则只追加内容】
#2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
rb
wb
ab
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
#3. 了解部分
"+" 表示可以同时读写某个文件
r+, 读写【可读,可写】
w+,写读【可读,可写】
a+, 写读【可读,可写】
3、操作文件的方法
#掌握
f.read() #读取所有内容,光标移动到文件末尾,也可以指定读取长度
f.readline() #读取一行内容,光标移动到第二行首部
f.readlines() #读取每一行内容,存放于列表中
f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333\n','444\n']) #文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
#了解
f.readable() #文件是否可读
f.writable() #文件是否可写
f.closed #文件是否关闭
f.encoding #如果文件打开模式为b,则没有该属性
f.flush() #立刻将文件内容从内存刷到硬盘
案例:完成文本文件的复制(边读边写):
r = open('1.txt','r',encoding='utf-8')
w = open('11.txt','w',encoding='utf-8')
for line in r: # 遍历就是一行一行读文件的流
w.write(line)
w.flush()
w.close()
r.close()
#将文件的关闭交给with,当with逻辑结束后,系统会自动释放文件
with open('1.txt','r',encoding='utf-8') as r:
with open('11.txt','w',encoding='utf-8') as w:
for line in r:
w.write(line)
w.flush()
完成文本文件的复制(先读后写):
with open('source.txt', 'r', encoding='utf-8') as f1, \
open('target.txt', 'a', encoding='utf-8') as f2:
# 读取一个字节,如果是行/文件等结束标识,就返回该标识,否则返回None
print(f1.newlines)
first_data = f1.read(9)
f2.write(first_data)
f2.flush()
print(f1.newlines)
second_data = f1.readline()
f2.write(second_data)
f2.flush()
last_data = f1.read()
f2.write(last_data)
f2.flush()
print(f1.newlines)
data = f1.read()
print(data)
借助读写,完成追加:
with open('1.txt','rt',encoding='utf-8') as f1:
data = f1.read()
data += '666'
with open('1.txt','wt',encoding='utf-8') as f2:
f2.write(data)
非文本文件采用二进制模式处理
with open('333.mp4', 'rb') as f1:
with open('666.mp4', 'wb+') as f2:
for line in f1:
f2.write(line)
游标:必须在b模式下操作,seek中偏移的是字节
方法:seek(偏移量,偏移位置)
偏移量:移动的字节数,负数是结合模式1,2往前偏移
偏移位置:
-- 0:从文件开始位置偏移
-- 1:从当前游标位置开始偏移
-- 2:从文件末尾位置开始偏移
文件内容:你好1234567890
# 游标读
with open('source.txt', 'rb') as f:
d1 = f.read(11)
print(d1)
# print(d1.decode('utf-8')) #字节类型涉及到解码
# 打印当前游标的位置
print(f.tell())
# 游标操作 - 从末尾位置开始
f.seek(-3, 2)
d2 = f.read()
print(d2.decode('utf-8')) # 890
# # 游标操作 - 从当前位置开始
# f.seek(-3, 1)
# d2 = f.read()
# print(d2.decode('utf-8')) # 34567890
# # 游标操作 - 从头开始
# f.seek(3, 0)
# d2 = f.read()
# # print(d2)
# print(d2.decode('utf-8')) # 好1234567890
# 游标写:会覆盖书写
with open('source.txt', 'rb+') as f:
f.seek(11)
# print(f.read())
f.write(b'000')
print("-------------------------------------")
# 案例
with open('001.png', 'rb') as f:
data = f.read()
print(len(data))
# 在大文件中,开头| 1/3 | 2/3 | 末尾 各取10个字节拼接成秒传的信息依据
# 形成秒传规则
tagData = b''
with open('001.png', 'rb') as f:
# 通过其他途径(sys模块)来获取文件总大小
data = f.read()
length = len(data)
# 开头
f.seek(0, 0)
d1 = f.read(10)
# 1/3
f.seek(length // 3, 0)
d2 = f.read(10)
# 2/3
f.seek(length // 3 * 2, 0)
d3 = f.read(10)
# 末尾
f.seek(-10, 2)
d4 = f.read(10)
tagData = d1 + d2 + d3 + d4
# 秒传依据
print(tagData)
newData = b""
with open('001.png', 'rb') as f:
data = f.read()
length = len(data)
f.seek(0, 0)
newData += f.read(10)
f.seek(length // 3, 0)
newData += f.read(10)
f.seek(length // 3 * 2, 0)
newData += f.read(10)
f.seek(-10, 2)
newData += f.read(10)
if newData == tagData:
print('秒传成功')
else:
print('慢慢传去吧')
# 自身创建文件操作流,可以清晰知道文件操作的模式 # 若文件是从外界获取的 with open('temp.txt','r',encoding='utf-8') as f: print(f.readable()) # 文件是否可读 print(f.writable()) # 文件是否可写
import sys
# 存放当前文件作为脚本执行的参数:['当前文件的绝对路径',手动传入的参数]
# 脚本文件执行:直接用python解释器运行该文件
print(sys.argv) #['G:/脱产7期/day09/sys传参的用法.py']
# 命令行执行
length = len(sys.argv)
if length > 1:
print("有指令传入")
cmd = sys.argv[1]
if cmd == '1':
print("新建文件")
with open('cmd.txt','w',encoding='utf-8') as w:
pass
elif cmd == '2':
print("书写文件")
with open(r'G:/脱产7期/day09/cmd.txt','w',encoding='utf-8') as f:
f.write("写入内容")
else:
print("输入有误")
else:
print("请输入指令")