什么是Unicode编码(详解)、什么是BOM头,如何对python文件添加BOM头
前言:
学习完什么是Unicode编码、什么是BOM头,如何对文件添加BOM头主要可以用于解决乱码问题
1、什么是Unicode(Universal Code)
Unicode是一种全球性字符编码方案,为世界上所有文字提供了唯一的数字标识符。它确保每个字符都有独一无二的编码,不受语言或书写系统的限制。说白了就是一张包含全世界所有文字的一个编码表,不管你用的上,用不上,不管是现在用的,还是以前用过的,只要这个世界上存在的文字符号,统统给你一个唯一的编码,这样就不可能有任何冲突了。不管你要同时显示任何文字,都没有问题。
Unicode的实现包括UTF-8、UTF-16和UTF-32等编码方式,其中UTF-8是最常见的。Unicode编码范围是0到0x10FFFF,理论上需要3个字节,但通常用4个字节表示,以确保处理文本更方便。这一方案解决了字符集差异问题,使得计算机能够更容易地处理和交换不同语言和书写系统的文本数据。
2、Unicode的实现方案
Unicode其实只是一张巨大的编码表。要在计算机里面实现,也出现了几种不同的方案。也就是说如何表示unicode编码的问题。
(1)UTF-8(UCS Transformation Format 8bit)
UTF-8(UCS Transformation Format, 8-bit)是一种用于表示 Unicode 字符的可变长度字符编码方案。它是一种兼容ASCII编码的编码方式,可以表示Unicode标准中的所有字符。
关键特点包括:
可变长度编码: UTF-8使用一到四个字节来表示字符,根据字符的不同而变化。ASCII字符(0-127)仍然使用一个字节表示,而其他字符使用两到四个字节。
兼容ASCII: UTF-8编码兼容ASCII编码,即ASCII中的字符在UTF-8中仍然使用一个字节表示,因此现有的ASCII文本可以被看作是UTF-8编码的子集。
前缀码: UTF-8中的每个字符都以一个前缀码开始,用于指示该字符需要多少字节来进行编码。这个前缀码的形式是通过第一个字节的高位来确定的。
UTF-8的格式如下:
单字节字符:0xxxxxxx
双字节字符:110xxxxx 10xxxxxx
三字节字符:1110xxxx 10xxxxxx 10xxxxxx
四字节字符:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
其中,x表示字符的二进制表示。
UTF-8的优势在于它对ASCII字符的兼容性,以及对不同范围的Unicode字符的有效编码。这使得它成为当前互联网和许多计算机系统中最常用的字符编码方式之一。
(2) UTF-16
UTF-16(UCS Transformation Format, 16-bit)是一种用于表示 Unicode 字符的字符编码方案。与UTF-8类似,UTF-16也是可变长度的编码,但它使用16位(两个字节)或32位(四个字节)的编码单元。
关键特点包括:
可变长度编码: UTF-16使用16位(两个字节)或32位(四个字节)编码单元来表示字符,具体取决于字符的 Unicode 编码点。基本上,大部分常用的字符(U+0000 到 U+FFFF)使用两个字节,而较大的字符(U+10000 到 U+10FFFF)使用四个字节。
基于编码点的表示: UTF-16直接使用 Unicode 编码点来表示字符,而不需要像UTF-8那样通过规则进行编码。这使得UTF-16更容易在处理大部分常用字符时保持紧凑。
字节序: 由于UTF-16使用多个字节表示一个字符,存在字节序的问题,即字节在内存中的排列顺序。UTF-16有两种字节序:大端序(Big-Endian)和小端序(Little-Endian)。UTF-16文本的开头通常包含一个特殊的字符(BOM,字节顺序标记),用于指示文本的字节序。
UTF-16广泛用于现代操作系统和应用程序,尤其是在 Windows 环境中。然而,在互联网中,UTF-8更为常见,因为它更紧凑,对ASCII字符兼容,并且避免了字节序的问题。
(3) UTF-32
UTF-32(UCS Transformation Format, 32-bit)是一种用于表示 Unicode 字符的字符编码方案。不同于UTF-8和UTF-16的可变长度编码,UTF-32使用固定长度的32位(四个字节)编码单元。
关键特点包括:
固定长度编码: UTF-32使用32位编码单元,每个字符都占用四个字节。这使得每个字符的编码长度相同,不像UTF-8和UTF-16那样根据字符的不同而变化。
直接表示 Unicode 编码点: 与UTF-16类似,UTF-32直接使用 Unicode 编码点来表示字符,而不需要像UTF-8那样通过规则进行编码。
字节序: 由于UTF-32使用32位编码单元,不存在字节序的问题,不需要字节顺序标记(BOM)。
UTF-32的主要优点是每个字符占用相同的固定空间,便于索引和处理。然而,它通常占用更多的存储空间,因为许多字符的 Unicode 编码点可以在更短的编码单元中表示。UTF-32在一些特定的应用场景中使用,但在互联网和通用应用中,UTF-8和UTF-16更为常见。
3、 编码存储差异
LE(little endian):小字节字节序,意思就是一个单元在计算机中的存放时按照低位在前(低地址),高位在后(高地址)的模式存放。
BE(big endian):大字节字节序,和LE相反,是高位在前,低位在后。
比如一个unicode编码为:0x006C49,如果是LE,那么在文件中的存放顺序应该是:49 6c 00如果是BE ,那么顺序应该是:00 6c 49。
4、编码格式的检测
到底采用什么编码,如果能检测就好了。因此专家给每种格式和字节序规定了一些特殊的编码,这些编码在unicode 中是没有使用的,所以不用担心会冲突。
这个叫做BOM(Byte Order Mark)头。
如下
编码 BOM表示
UTF-8 EF BB BF
UTF-16(大端序BE) FE FF
UTF-16(小端序LE) FF FE
UTF-32(大端序BE) 00 00 FE FF
UTF-32(小端序LE) FF FE 00 00
5、什么是文件的BOM头(字节顺序标记(ByteOrderMark))
在utf-8编码文件中BOM在文件头部,占用三个字节,BOM是用来判断文本文件是哪一种Unicode编码的标记,其本身是一个Unicode字符(“\uFEFF”),位于文本文件头部。
1)实际应用场景
当我们在windows下做文本处理时,可能经常会遇到带BOM的utf-8编码文件,这时需要对文件头BOM处理一下,不然会带来一些不好的影响。
首先要明确一点,在Python2中,codecs.BOM_UTF8是str类型,如果要与unicode进行对比的话需要转换一下。
2)如何对csv文件添加BOM头
with open(file_path, mode='w', newline='', encoding='utf-8-sig') as file:
在Python中,使用**utf-8-sig**
编码可以在写入文件时自动添加UTF-8 BOM头。当你使用utf-8-sig
编码时,Python会在文件开头自动插入EF BB BF
字节序列。
所以通过检测文件前面的BOM头,基本能确定编码格式和字节序。但是这个BOM头只是建议添加,不是强制的,所以不少软件和系统没有添加这个BOM头(所以有些软件格式中有带BOM头和NoBOM头的选择),但是建议添加