Java内码编码之UTF-16讲解 [Java][编码]

Java内码编码之UTF-16讲解

Java中采用了UTF-16的格式, 该格式中使用两个字节表示一个基本字符, 所以Java中的char类型占用的存储空间也就是两个字节, 可两个字节最多也就表示60000多个字符, 而Unicode中现在收录了超过了14万个字符, 那么剩下的字符是如何表示的?

  • 其实UTF-16所说的使用两个字节表示一个基本字符并不是说只能使用两个字节表示字符, 而是指的是使用两个字节为最小单位, 这个单位我们通常称之为: “代码单元(code unit)”, 对于基本字符, UTF - 16中使用一个代码单元, 也就是两个字节表示, 对于剩下的字符我们就称之为辅助字符, 辅助字符使用两个代码单元, 也就是四个字节表示, 这样表示14万字符就绰绰有余了
    • 为了简化表达, 通常使用u + 0000 ~ u + FFFF表示基本字符, 使用u + 10000 ~ u + 10FFFF表示辅助字符, 这些用来表示字符的编号我们称之为:码点.

Java中如果是将一个辅助字符放到一个char中的时候就会编译出错, 因为我们的辅助字符需要使用两个代码单元, 也就是四个字节来表示, 而我们的一个char知识两个字节, 所以我们对于辅助字符要使用字符串变量来接收(String底层会使用两个代码单元, 也就是四个字节来存储一个辅助字符)

  • eg:emoji表情(emoji表情就是一个辅助字符,需要使用四个字节表示)

易错情况:

我们如果调用charAt()方法获取某个位置的字符的时候如果是获取到了某个辅助字符的一对char中的一个的时候就会出现乱码

如果我们一个字符串中有辅助字符, 那么我们调用length()方法获取结果的时候同样会有一定的问题, 因为字符串中的length()方法其实是获取到代码单元的数量, 而一个辅助字符占用了两个代码单元

  • 所以如果字符串中有辅助字符, 调用方法的时候一定要注意:

如果字符串中有辅助字符, 并且这个时候我们要求出字符串的真正长度的时候, 我们可以通过码点的形式来获取, 一个码点就是代表了一个字符

  1. String对象的codePointCount(0,s1.length)方法就可以获取到字符串中从0位置到最后一个位置的码点的数量
  2. String对象的codePoints()方法可以获取字符串中所有的码点,以流的形式,
    • 码点: 就是表示一个字符的编码, 不管是基本字符或者是辅助字符我们都是使用一个码点表示的
    • 我们可以先使用codePoints()方法获取到对应的码点组成的流, 然后调用toArray()方法就可以得到对应的码点数组
      • 这个码点数组的长度就是字符串中真正的字符的数量

使用Character类中的isSupplementaryCodePoint()方法判断参数码点是否是表示一个辅助字符

使用Character类的isSurrogate()方法判断参数char是否是一个辅助字符的一个代码单元

  • 也就是如果我们要判断使用charAt()方法获取到的字符是否是一个辅助字符的一个代码单元的时候就可以调用此方法
  • 这个方法中就是传入一个代码单元, 然后判断这个代码单元是否是某个辅助字符的两个代码单元中的一个

补充:

我们在前端向服务器发送一个请求的时候如果请求数据中是24个英文字母, 这个时候我们在请求头中的content-length中可以看到这24个英文字母占用的字节数是24个字节, 就是说这个时候就是使用的utf-8编码进行存储的, 此时到了java中就是外码(utf-8)

  • 但是当将这个字符串传输到Java中的时候如果保存到一个String变量中的时候, 这个字符串的长度就不是24个字节了, 而是48个字节, 因为存储到内存中的时候就是使用的内码了, 而Java中的内码是UTF-16, 在UTF-16中除了辅助字符之外的字符都是占用了两个字节, 只有辅助字符是占用了4个字节的, 所以这也就是为什么我们将这个字符串保存之后可以计算出字符串长度为24了, 我们的length()方法是通过代码单元进行分割的,而一个代码单元占两个字节

    • 所以我们我们使用了utf-16将字符串保存到中之后这些英文字符都会占用两个字节进行存储, 所以我们才可以正确的使用String类的length()方法求得字符串长度
  • 小结: 其实就是Java中内存中存储字符的时候都是使用utf-16进行存储的, 所以只要是存储到内存中的字符都是使用2个或者4个字节进行存储的
  • length(),charAt()方法等等很多方法都是使用代码单元进行的分割, 而不是码点, 所以对于这种方法操作的字符串中一定不能有辅助字符, 否则就会出问题, 因为辅助字符是使用4个字节, 也就是两个代码单元存储的

    • 但是注意: 不管是普通字符或者是辅助字符都是用一个码点表示的, 所以如果字符串中有辅助字符的时候我们就要使用码点来作为区分依据

你可能感兴趣的:(java,java,jvm,开发语言)