1 字符编码
1、字符编码:
字符码(charcter code)指的是用来代表字符的编码。读者在输入和存储文档时都要使用字符编码。
ASCII 码(单字节): 能够支持256个字符编码.
ANSI(双字节):能够支持65000个字符编码,中文简体编码 GB2312 实际上是 ANSI 的一个代码页,不同的代码页的内码无法再其他代码中正常显示,日中文/繁体中文/简体中文使用了不同的代码页,
2、Unicode:
Unicode也是一种字符编码方法,只是它是由国际组织设计,能够容纳全世界全部语言文字的编码方案.
当中UTF-16和Unicode编码大致一样, UTF-8 为了节省存储空间,以8位为单元对Unicode进行编码。
bom(byte order mark) 出现在文本文件的头部,unicode 编码中用来标识文件采用哪种格式的编码,UTF-8 的 BOM 编码是 EF BB BF
。
下面是使用 Binary Viewer 工具查看不同编码的文本文件,其内容为’hello world!你好!’:
utf-8
ansi
2 为什么需要字符编码
字符编码主要是为了实现字符信息(文本)在计算机系统中的存储与传输:
字符,不管是中文字符还是英文字符,在计算机系统中都是以字节的形式来存储的,比如保存了 hello world!你好!
的 txt 文件,指定文件为 utf-8 格式,那么在硬盘中存储的信息是 00 EF BB BF 68 65 6C 6C 6F 20 77 6F 72 6C 64 21 20 10 77 6F 72 6C 64 21
。当我们用记事本(本质上是一个程序)打开 txt 文件,记事本会根据编码识别相应的字符,然后在记事本的内容区域显示字符对应的图形。
字符图形可以是矢量图,也可以是位图。
3 字节,字符,字符串
Java
char 是 Java 的基本类型(原类型) ,默认字符集为 utf-8。多个字符的序列可以是字符数组(mutable),也可以字符串(immutable)。
char 与 byte 是不同的,byte 是数据存储的基本单元,任何数据信息,比如对象,图片,程序,最终都是以 byte 的形式来存储(分为大端、小端)的。char 是字符,同一字符的不同字符编码对应的 byte 流是不一样的。
在 Java 中使用 InputStream/OutputStream 来读写字节(byte)流,使用 Reader/Writer 来读写字符(char)流。
class HelloChar{
public static void main(String[] args) {
String s = String.valueOf(new char[]{'你', '好'});
System.out.println(s); // 你好
char c = '你';
System.out.println(c); // 你
byte[] b = s.getBytes();
bytes2HexString(b); // E4BDA0E5A5BD
}
public static void bytes2HexString(byte[] b) {
String ret = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[ i ] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
System.out.print(ret);
}
}
Python
Python 没有 char 类型,一个字符等同于长度为 1 的字符串,字符串与字节流的转换形式更简洁:
s = "hello world!你好!" # 默认为 utf-8
# 方法 1
u = bytes(s, encoding='utf-8') # b'hello world!\xe4\xbd\xa0\xe5\xa5\xbd!'
g = bytes(s, encoding='gb2312') # b'hello world!\xc4\xe3\xba\xc3!'
# 方法 2
u2 = s.encode('utf-8')
g2 = s.encode('gb2312')
str(u, encoding='utf-8') # "hello world!你好!"
str(g, encoding='gb2312') # "hello world!你好!"