2 回答
TA贡献1890条经验 获得超9个赞
第一个问题
对于您的第一个问题:这些字节是 BOM 代码,它们指定多字节编码(例如 UTF-16)的字节顺序(无论是最重要的还是最重要的)。
第二个问题
每个 ASCII 字符都可以在 UTF-8 中编码为单个字节。但是 ASCII 不是 8 位编码,它为每个字符使用 7 位。事实上,所有代码点 >= 128 的 Unicode 字符至少需要两个字节。(原因是您需要一种方法来区分 200 和第一个字节恰好是 200 的多字节代码点。UTF-8 通过使用字节 >= 128 来表示多字节代码点来解决这个问题。)
'È' 不是 ASCII 字符,因此不能用 ASCII 表示。这解释了第二个输出:63 是字符“?”的 ASCII。实际上,该getBytes(Charset)
方法的 Javadoc 指定不可映射的输入映射到“默认替换字节数组”,在本例中为“?”。另一方面,要获取第一个 ASCII 字节数组,您可以CharsetEncoder
直接使用,这是一个更底层的 API,不会执行此类自动替换。(当您检查该encode
方法的结果时,您会发现它返回了一个CoderResult
表示错误的实例。)
第三个问题
Java 8String
内部使用 UTF-16,但在与其他软件通信时,可能会出现不同的编码,例如 UTF-8。该Charset.defaultCharset()
方法返回虚拟机的默认字符集,它取决于操作系统的语言环境和字符集,而不是 Java 字符串内部使用的编码。
TA贡献1772条经验 获得超8个赞
让我们备份一下……
Java 的文本数据类型使用 Unicode 字符集的 UTF-16 字符编码。(和 VB4/5/6/A/Script、JavaScript、.NET、...一样。)您可以在使用字符串 API 执行的各种操作中看到这一点:索引、长度、...。
库支持使用各种编码在文本数据类型和字节数组之间进行转换。其中一些被归类为“扩展 ASCII”,但说明这是一个非常差的替代命名实际使用的字符编码的替代品。
一些操作系统允许用户指定默认字符编码。(不过,大多数用户不知道也不关心。)Java 试图接受这一点。只有当程序理解用户的输入是字符编码或输出应该是时,它才有用。本世纪,处理文本文件的用户更喜欢使用特定的编码,在系统之间保持不变地进行通信,不喜欢有损转换,因此这个概念没有任何用处。从程序的角度来看,它永远不是你想要的,除非它正是你想要的。
如果转换有损,您可以选择替换字符(例如“?”)、忽略它或抛出异常。
根据编码的定义,字符编码是字符集的代码点(整数)与一个或多个代码单元之间的映射。代码单元是固定大小的,代码点所需的代码单元数量可能因代码点而异。
在库中,拥有一个代码单元数组通常没有用,因此它们需要进一步转换为字节数组/从字节数组转换。byte
值的范围确实从 -128 到 127,但是,这是 Java 解释为二进制补码 8 位整数。由于字节被理解为编码文本,因此将根据字符编码规则解释这些值。
由于某些 Unicode 编码的代码单元长度超过一个字节,因此字节顺序变得很重要。因此,在字节数组级别,有 UTF-16 Big Endian 和 UTF-16 Little Endian。在传输文本文件或流时,您将发送字节并共享编码知识。这个“元数据”是理解所必需的。因此,例如 UTF-16BE 或 UTF-16LE。为了使这更容易一点,Unicode 允许文件或流的一些元数据开头来指示字节顺序。它被称为字节顺序标记(BOM)。因此,外部元数据可以共享编码(例如,UTF-16),而内部元数据则共享字节顺序。即使字节顺序不相关,Unicode 也允许存在 BOM,例如 UTF-8。所以,
1) 您在一些 Unicode 编码输出中看到了 BOM。
2) È 不在 ASCII 字符集中。在这种情况下会发生什么?我经常喜欢一个例外。
3)您在测试时为您的帐户使用的系统可能已将 UTF-8 作为默认字符编码,这对您想要的方式以及在该系统上对文本文件进行编码是否重要?
添加回答
举报