字符编码与文件的处理

1.字符编码

1.计算机内部存储数据都是以二进制数字的形式存储
	计算机基于电工作 而电信号只有高低电平两种状态
    也就意味着计算机的世界里只能识别两种状态
    我们人为的将高电平定义为数字1
    低电平定义为数字0

    
2.单位换算(重要)
	比特位bit(二进制数的个数)
    8bit = 1bytes(字节)
    1024bytes = 1KB
    1024KB = 1MB
    1024MB = 1GB
    1024GB = 1TB
    1024TB = 1PB
   
# 字符编码的研究仅限于文本文件(******)


3.为什么我们人类在使用计算机输入字符的时候电脑展示是人类能够看懂的字符
而计算机内部只识别01二进制
	00001010			我
    00001101              你
    计算机二进制			设定好的对应关系		人类的字符
    
# 字符编码表
	规定了人类的字符与数字之间的对应关系

2.字符编码发展史

一家独大
	计算机是由美国人发明的 美国人需要计算机能够识别英文
    所以发明了ASCII码(字符编码表)
    	记录了英文与数字的对应关系
        	1bytes来表示所有的英文及符号
    			8bit	256
# 所有的英文字母及符号加起来其实也不会超过128种可能
群雄割据
	中国
    	中国人为了计算机能够识别中文发明了GBK码
        GBK码表
        	记录了中文、英文与数字的对应关系
            	2bytes来表示中文及符号
                	16bit       65535
                1bytes来表示所有的英文及符号
# 生僻字可能会使用更多的bytes来表示
        
 日本
    日本人为了计算机能识别日文发明了shift_JIS码
        shift_JIS码表
        记录了日文、英文与数字的对应关系
        1bytes来表示所有的英文及符号
            	
 韩国
	韩国人为了计算机能识别韩文发明了Euc_kr码
        Euc_kr码表
        记录了韩文、英文与数字的对应关系
        1bytes来表示所有的英文及符号
        
天下一统
    群雄割据导致数据交互不通畅(乱码)
    unicode万国码
    兼容万国字符
    所有的字符同意使用2bytes表示 不够增加更bytes
utf8
    unicode transformation format
    英文还是用1bytes
    中文改用3bytes
# 内存使用的编码表是unicode 硬盘使用的是utf8
'''已经你们只需要记住文本文件编码统一使用utf8即可'''

3.字符编码实操

1.解决文件乱码的核心
	文件以什么编码存的就以什么编码取
2.编码与解码(重要)
	# 编码
    	将人类的字符按照指定的编码转换成计算机能够识别的数据
        encode()
    # 解码
    	将计算机能否识别的数据按照指定的编码转换成人类能够读懂的字符
        decode()
3.python解释器默认编码
	python2默认的是ASCII码
    	在python2中定义字符串在前面加一个字母u
        文件头指定编码
        	# -*- conding:utf8 -*-
            name = u'jason'
    python3默认的是utf8码

4、文件操作

操作系统
	windows mac linux
双击文件
	硬盘转 磁头读取数据
保存文件
	硬盘转 磁头写入数据
 
我们在操作文件的时候其实操作的是硬盘
'''
文件其实是操作系统暴露给我们可以简单快捷的操作硬盘的接口
'''

# 绝对路径与相对路径
	绝对路径
    	非常详细的路径描述
        	无论什么人什么位置都可以找到
    相对路径
    	有一个参考
        	只有对应的人才可以找到

res = open(r'a.txt','r',encoding='utf8')
print(res.read())
res.close()



# 打开a.txt 使用变量名f指代改文件
with open(r'a.txt','r',encoding='utf8') as f:
    print(f.read())  # 读取文件内容
# with子代码运行结束之后会自动调用close关闭文件资源
"""
with open(文件路径,读写模式,编码格式) as 变量名:
    子代码块
文件路径是必须的
读写模式和编码格式是可选的
"""


# 如果不指定读写模式 那么默认使用r
# 如果不指定编码格式 那么默认使用当前计算机内部默认编码
"""在中国所有的windows电脑内部默认的编码是gbk"""
with open(r'a.txt') as f:
    print(f.read())  # 读取文件内容


# 取消转义
res = r'D:\day08\a.txt'
res1 = r'D:\day08\n.txt'
res2 = r'D:\day08\t.txt'
print(res,res1,res2)

5、文件处理

1、控制文件读写操作的模式
r(默认)
w
a

2、控制文件读写内容的模式
t(默认的):读写都是以字符串为单位的,只适用于文件文件,必须指定encoding参数
b:读写都是以bytes为单位的,适用于所有文件,一定不能指定encoding参数


r模式:只读模式,如果文件不存在则报错,文件存在则文件指针处于文件开头

f = open('a.txt',mode='rt',encoding='utf-8')
print(f.read())  # 显示文件内容,显示所有a.txt信息,且光标移动到最后
print('='*50)	# 分隔符号
print(f.read())  # 从上面光标位置开始读取内容 ,显示内容为空 
print(f.readable())  # True	
print(f.writable())  # False
f.close()  # 关闭

w模式:只写模式,如果文件不存在则创建空文档,文件存在则清空,文件指针处于文件开头
简单记忆:w模式下每次都是新建文件将之前的原文件覆盖,必须要备份以免数据丢失
f = open('a.txt',mode='wt',encoding='utf-8')
f.write("你好\n")
f.write("哈哈哈\n")
f.write("我擦勒\n")
f.close
f = open('a.txt',mode='wt',encoding='utf-8')
f.write("你好\n哈哈哈\n我擦勒\n")  # 覆盖a.txt文件,									显示上述内容
print(f.readable())  # 可读  False
print(f.writable())  # 可写  True
f.close()  # 关闭
总结:w模式,在打开了文件不关的情况下,连续的write写入,新写的内容永远跟在后面

a模式:只追加写模式,如果文件不存在则创建空文档,文件存在不会清空,文件指针处于文件末尾
f = open('c.txt',mode='at',encoding='utf-8')
f.write("4444\n")
f.write("555\n")
f.write("6666\n")  # a模式永远写在后面
print(f.readable())  # False
print(f.writable())  # True
f.close()  # 关闭

总结:a模式,在打开了文件不关的情况下,连续的write写入,新写的内容永远跟在后面,这一点与w模式相同
   不同的是,在打开了文件关闭然后重新打开的情况下,a模式永远写在后面


b模式:读写都是以bytes为单位的,适用于所有文件,一定不能指定encoding参数
with open('1.mp4',mode='rb') as f:  # 视频格式
    res = f.read()
    print(res.decode('utf-8'))  # 报错 不能解码


with open('a.txt',mode='rb') as f:  # 文本文件
    res = f.read()
    print(res.decode('utf-8'))  # 文本文件 可以解码读取内容


with open('a.txt',mode='ab') as f:
    f.write("啊手动阀手动阀".encode('utf-8'))  # 直接在文件最后追加


例:文件拷贝功能
# 方案一: 整体复制,缺陷:文件过大内存可能会存在溢出
with open('1.mp4',mode='rb') as f1,open(r'D:\1111111.mp4',mode='wb') as f2:
    res = f1.read()
    f2.write(res)
    f2.write(f1.read)  #复制文件至指定位置

# 方案二: 
储备知识: 
with open('a.txt',mode='rt',encoding='utf-8') as f:
    # f.read()
    for line in f:
        print(line,end='') # end''可以删除\n 不加的话每行之间会有空格


with open('1.mp4',mode='rb') as f:
    for line in f:
        print(line)  # 解码后跳出二进制码

具体实现:
with open('1.mp4',mode='rb') as f1,open(r'D:\1111111.mp4',mode='wb') as f2:
    for line in f1:  # 将1.mp4转码后进行分行复制
        f2.write(line)  # 将分行后逐条内容复制到f2指定的位置


可读可写  # 如下命令不怎么使用
r+t
w+t
a+t

r+b
w+b
a+b

with open('a.txt',mode='r+t',encoding='utf-8') as f:
    print(f.readable())  # True
    print(f.writable())  # True
    print(f.read())  
    f.write("22222222222222222222\n")  # 在文件最后添加新增的内容



with open('a.txt',mode='w+t',encoding='utf-8') as f:
    print(f.readable())   # True
    print(f.writable())   # True

6、控制文件指针移动

# f.seek移动的全都是字节个数
# f.seek(字节个数,0)  # 文件最开始的地方
# f.seek(字节个数,1)  # 指针移动到的地方
# f.seek(字节个数,2)  # 文件末尾

# ps:只有0模式可以t下使用,其中1和2模式只能在b模式下使用,但是无论在t模式还是b模式下,移动的都是字节个数

# 例如:a.txt 内容:hello你好kasjdkla

with open(r"a.txt",mode="rt",encoding="utf-8") as f:
    print(f.tell()) # 0  查看当前文件指针距离文件开头的位置,输出结果为0
    f.seek(9,0)  # 9 查看当前文件指针距离文件开头的位置,输出结果为9
    f.seek(3,0)  # 3 查看当前文件指针距离文件开头的位置,输出结果为3
    print(f.tell())  # 3 查看当前文件指针距离文件开头的位置,最终输出结果为3


with open('a.txt',mode='rb') as f:
    print(f.tell())  #0  从指针当前位置往后移动0个字节,而此时的当前位置就是文件开头
    f.seek(9,1)  # 9 从当前位置往后移动9个字节,而此时的当前位置就是文件开头
    f.seek(3,1)  # 12 从当前位置往后移动3个字节,而此时的当前位置9
    print(f.tell())  # 12 从当前位置往后移动3个字节,而此时的当前位置9

with open('a.txt',mode='rb') as f:
    print(f.tell())  #0 从指针当前位置往后移动0个字节,而此时的当前位置就是文件开头
    f.seek(0,2)  # 参照文件末尾移动19个字节, 即直接跳到文件末尾
    print(f.tell())  # 19 输出结果为:19

with open('a.txt',mode='ab') as f:
    print(f.tell())  # 19 追加模式指针移动到最后,显示全部字节


# Linux命令:tail -f access.log

7、文件修改的两种方式

# 例如:a.txt 内容:hello你好kasjdkla

with open('a.txt', mode='r+t', encoding='utf-8') as f:
	f.seek(9,0)
	f.write("hello")  #hello你�hellojdkla 

# PS:文件修改不是修改,而是执行覆盖命令

'''
文件修改的原理:
把硬盘数据读入内存,在内存修改完毕后,再覆盖回硬盘
'''
# 具体来说又分为两种方案
# 方案一:  利:不占硬盘空间 弊:占据内存空间
with open('test.txt',mode='rt',encoding='utf-8') as f:
     data = f.read()

 with open('test.txt',mode='wt',encoding='utf-8') as f:
     f.write(data.replace('egon','EGON'))


# 方案二:  利:不占内存空间 弊:占据硬盘空间(2倍)
import os

with open('test.txt',mode='rt',encoding='utf-8') as f1,\
        open('.test.txt.swp',mode='wt',encoding='utf-8') as f2:
    for line in f1:
        f2.write(line.replace('EGON',"egon"))

os.remove('test.txt')
os.rename('.test.txt.swp','test.txt')
posted @ 2021-06-17 17:06  Ame林汀  阅读(161)  评论(0)    收藏  举报