Java字符编码—Unicode与UTF-8的区别

Unicode字符集

Unicode,是计算机科学领域里的一项业界标准。为每种语言中的每个字符设定了统一并且唯一的整数值,把这个数值称为码点(Code Point)。
但是它并不规定计算机如何存储和传输这个数值(以多少个字节存储,是定长还是变长,Unicode没有字节长度的概念)。

Unicode 定义了一个码点空间包含1,114,112个码点,范围从0到0x10FFFF,也就是说,它仅仅是一个字符映射集。其中 0x0000 ~ 0xFFFF 的字符表示常用字符集,称 BMP字符,0x10000 ~ 0x10FFFF 字符叫增补字符。

Unicode 目前规划的总空间是17个平面(平面0至16),0x0000 至 0x10FFFF,每个平面有 65536 个码点。
例如,"AB中国"这个字符串,对应的 Unicode 编码为:

A  -> \u0041
B  -> \u0042
中 -> \u0049
国 -> \u56FD

Unicode的实现

同一 Unicode 值可以被编码成不同的二进制表示,以便在存储和网络上传输。Unicode的实现:UTF-8、UTF-16、UTF-32、UCS-2等。

UTF-8, Unicode Transformation Format – 8-bit

  • 使用 1 ~ 4 个字节变长编码表示「1,112,064」个 Unicode 码点
  • 兼容 ASCII
  • 码点数值越小,使用的字节数越少,出现的频率越高

UTF-16

  • 使用 1 ~ 2 个 16bit 变长编码表示「1,112,064」个 Unicode 码点
  • 它扩展于固定16bit长度的UCS-2

UTF-32

  • 4 字节定长编码
  • 其高位均为0,空间浪费比较严重,因此应用很少

Java 使用何种编码

Java char 占 2 个字节,使用 UTF-16BE 表示一个字符。由于它只使用 2 个字节,所以 char 只用能表示部分 UTF-16 编码,即 0x0000 ~ 0xFFFF。对于 4 字节的 UTF-16,需要使用 2 个 char。

String 始终是按 UTF-16BE 处理字符的,对 BMP 字符,使用一个 char,两个字节;对于增补字符,使用两个 char,四个字节。以上是由 Java language spec 规定的。

Java 源文件默认采用平台编码存储,Linux/Unix 是 UTF-8,Window 采用 GBK。一般常用的 IDE 如 Intellij IDEA 和 Eclipse 都能提供多种编码。编译器 javac 读取 Java 源文件时,如果不显示指定 -encoding,则默认以 Charset.defaultCharset() 读取,如果与源文件的编码不同,则会报错。

javac -encoding gbk/utf-8 仅告诉编译器以何种编码读取 Java 源文件,然后编译器在编译时就用指定的编码把源文件的字符串转化为UTF-8字符串。

不管 Java 源文件是什么编码,Java class 字节码文件中字符串字面量始终是 UTF-8 编码,这是由 JVM spec 规定。

UTF-8 和 GBK2312 编码的 Java 源文件,分别编译成 class 文件,两者相同。

System.out、PrintStream 将会在输出之前,把字符串从 UTF-16 转换成默认系统编码(JVM 从操作系统读取)。

Java 中把 String 转换成字节码,默认使用平台默认的编码。看看 getBytes 的注释。

    /**
     * Encodes this {@code String} into a sequence of bytes using the
     * platform's default charset, storing the result into a new byte array.
     *
     * 

The behavior of this method when this string cannot be encoded in * the default charset is unspecified. The {@link * java.nio.charset.CharsetEncoder} class should be used when more control * over the encoding process is required. * * @return The resultant byte array * * @since JDK1.1 */ public byte[] getBytes() { return StringCoding.encode(value, 0, value.length); }

你可能感兴趣的:(Java字符编码—Unicode与UTF-8的区别)