字符编码、文件处理

字符编码

因为计算机的工作原理就是靠电,而电的特性就是高低电平(0,1),所以说计算机只能读懂类似于一串010110101011001...这样的数字,而人类的语言却是很复杂的,对于计算机来说根本理解不了,这就需要某一种方式来转换,能够让两者之间进行交互,所以产生了字符编码。

定义:将字符一一对应到特定数字的标准。

  • 字符编码的发展史

最早的字符编码是ASCII,只规定了英文字母、数字和一些特殊符号与数字的对应关系。最开始只用8位来表示一个字节,即2**8=256,所以它最多只能表示256个字符,随后相继出现了gbk,shift_jis,Euc_kr等各个国家的编码,后来又出现了Unicode,能够兼容各国的编码。

      

  • 关于乱码的问题

由于世界上各个国家的编码方式都不一样,所以想要在全球范围使用同一个计算机是不可能的(各个国家的计算机内存和硬盘中用的是自己国家的字符编码),对于本国来说,如:中国的gbk编码,能够识别中文和英文,但是它识别不了泰语、韩语、日语等等,同样,日本的Shift_JIS也只能识别英文、日文,识别不了中文。所以说每个国家的编码只能在本国使用,再本国使用就不会有什么乱不乱码的问题了。
但是,要想通用计算机,那就有问题了。首先,各个国家的编码互不兼容,所以根本没法通用。那第二个问题(乱码问题),说白了乱码就是编码不统一造成的,那怎么统一呢?(目前来看,让全球统各国用同一种编码是不可能了),所以目前要解决的问题是:怎么能有一种既能兼容各国编码又能与各国的字符编码都有映射关系,那这样就可以与其他的编码任意转换了,这就是Unicode(定长万国码),但是Unicode自身也存在一个问题,统一用2Bytes标识一个字符,这对存储一篇英文写的文本来说就是浪费空间,其次,如果文件过大,将会增加计算机的I/O次数,影响计算机的执行效率,所以随后又产生了UTF-8(可变长,全称Unicode Transformation Format)来解决这个问题。

总结内存中统一采用Unicode,虽然浪费空间,但是可以转换成任意编码,能保证不乱码,硬盘则采用各种编码,保证存放于硬盘的数据量很小,能提高传输效率与稳定性。

所以保证不乱码的前提就是,用哪种字符编码编码的,那就应该用同样的字符编码去解码!!!

 文件处理

  • 文件操作

文件的概念来源于操作系统,是操作系统提供的一种虚拟的储存数据的单位。所以我们只要关注操作文件的流程就OK!

# 1、打开一个文件,得到一个文件句柄并赋值给一个变量
f=open('s.txt','r',encoding='utf-8')

# 2、通过句柄对文件进行操作
data=f.read()

# 3、操作完关闭文件
f.close()

分析:应用程序向操作系统发起调用指令open(),然后操作系统打开一个文件,并返回这个文件句柄给应用程序,再由应用程序将文件句柄赋值给变量f

  • 打开一个文件包含两部分资源

1、操作系统级打开的文件(回收时f.close())
2、应用程序级的变量(回收时 del f)

注意点:操作系统打开文件时如果我们不指定字符编码,那操作系统就会默认为它自己的编码去打开文件(Windows是gbk,Linux是UTF-8),有时会造成乱码的现象,所以,就要用编码(encode)时的字符编码去打开(解码decode)该文件。f=open('s.txt','r',encoding='utf-8')

  • 打开文件的模式

1、文本模式(默认)

文本打开的方式
r---只读模式(默认模式,文件必须要存在才能打开,否则会报错)
w---只写模式(不可读,文件不存在时会自动创建,有则清空内容)
a---追加写模式(不可读,文件不存在时会自动创建,存在则只在文件最末尾追加内容)

2、非文本模式(Bytes)

非文本模式打开方式
rb
wb
ab
非文本文件读取到的内容是字节类型(Bytes),写入时也要提供字节类型,不能指定字符编码

  • 操作文件的方法
# 读
f.read()    # 读取文件所有内容,同时光标移动到文件末尾
f.readline()    # 读一行内容,光标移动到第二行开头位置
f.readlines()   # 读取文件每一行内容,存放于一个列表中

# 写
f.write()   # 针对文本模式,要自己写上换行符;对b模式,除了要写换行符,还要对写的内容编码.encode()
f.writelines(['aaa\n','bbb\n'])  # 文件模式
f.writelines([bytes('aaa\n',encoding='utf-8'),'bbb\n'.encode('utf-8')])  # b 模式

光标在文件内的移动

f.seek(offset,whence)
offset:偏移量(光标移动的字节数)
whence:参照物(0,1,2)

0、代表默认参照文件开头,通用于t与b模式
1、代表参照光标所在的当前位置,只能用于b模式
2、代表参照文件的末尾,只能用于b模式

# t模式下光标的移动
with open('a.txt', 'rt', encoding='utf-8') as f:
    msg = f.read(1)  # 读到的是一个字符----你
    print(msg)
    f.seek(6, 0)  # 将光标从文件头移动6个字节
    msg1 = f.read(1)  # 读到的是一个字符----啊
    print(msg1)


# b模式下的光标移动
with open('a.txt', 'rb') as f:
    msg = f.read(3)  # 从头开始读3个字节----你
    print(msg.decode('utf-8'))
    f.seek(6, 1)  # 从当前读到的位置开始光标移动6个字节
    msg1 = f.read(4)  # 再读出4个字节----hell
    print(msg1.decode('utf-8'))


# b模式下的光标移动之倒移
f.seek(0, 2)    # 会直接将光标移动到文件末尾

with open('a.txt', 'rb') as f:
    f.seek(-5, 2)  # 文件内光标从末尾往前移动5个字节
    msg1 = f.read(5)  # 读取5个字节----hello
    print(msg1.decode('utf-8'))
t/b模式中光标的移动

注意文件内指针的移动,只有在t模式下的read(n),n才表示的是字符的个数,除此之外,其余的都表示的是字节(Bytes)!!

修改文件的两种方式

# d.txt内容
'''
Jack说他很帅
Jack说他很浪
呵呵笑了笑Jack
'''
with open('d.txt', 'rt', encoding='utf-8') as f:
    msg = f.read()

with open('d.txt', 'wt', encoding='utf-8') as f:
    f.write(msg.replace('Jack', '帅逼'))
方式一:
import os

with open('d.txt', 'rt', encoding='utf-8') as read_f, \
        open('d.txt.x', 'wt', encoding='utf-8') as wirte_f:
    for info in read_f:
        wirte_f.write(info.replace('帅逼', 'Jack'))

os.remove('d.txt')
os.rename('d.txt.x', 'd.txt')
方式二:
总结:
	优点
		方式一:同一时间内硬盘中只有一份数据存在
		方式二:对内存的占用很少
	缺点
		方式一:文件过大时会占用太多内存,降低运行效率
		方式二:同一时间硬盘中会有两份数据存在

猜你喜欢

转载自www.cnblogs.com/rongge95500/p/9372228.html
今日推荐