通常,当我需要将字符串转换为不带参数时byte[]
使用。getBytes()
我被检查它不是保存我应该使用字符集。为什么我应该这样做 - 字母“A”将始终被解析为0x41
?不是吗?
3 回答
通常,当我需要将字符串转换为 byte[] 时,我会使用不带参数的 getBytes()。
现在停止这样做。我建议您始终指定编码。如果你想使用平台默认编码(如果你不指定一个,你会得到什么),然后明确地这样做,这样它就更清楚了。但无论如何,这应该很少是这种方法。我个人几乎在所有情况下都使用 UTF-8。
为什么我应该这样做 - 字母“A”将始终被解析为 0x41?不是吗?
没有。例如,使用 UTF-16,“A”将是两个字节 - 0x41 0x00 或 0x00 0x41(取决于字节序)。在 EBCDIC 编码中,它可能是完全不同的东西。
大多数编码以相同的方式处理 ASCII 字符 - 但 ASCII 以外的字符在不同编码中的表示方式非常不同(许多编码仅支持 Unicode 的一个子集)。
有关更多详细信息,请参阅我关于 Unicode(以 C# 为重点,但原理相同)的文章 - 以及指向比您可能想要的更多信息的链接。
不同的字符编码导致字符被解析的不同方式。在 Ascii 中,“A”肯定会解析为 0x41。在其他编码中,这将有所不同。
这就是为什么当您访问某些网页时,您可能会看到一堆奇怪的字符。浏览器不知道如何解码它,所以它只是解码为默认值。
一些背景知识:当文本存储在文件中或通过套接字在计算机之间发送时,文本字符作为位序列存储或发送,几乎总是以 8 位字节分组。这些字符都在 Unicode 中定义了数值,因此“A”始终具有值 0x41(好吧,在 Unicode 字符集中,希腊和俄罗斯字母表中实际上还有另外两个 A,但这不相关)。但是有很多机制可以解决当存储在文件中或发送到另一台计算机时,这些数字代码被转换为一系列位。在 UTF-8 中,0x41 表示为 8 位(字节 0x41),但其他数值(代码点)将通过重新排列位的算法转换为 16 位或更多位;在 UTF-16 中,0x41 表示为 16 位;还有其他编码,如 JIS 和一些能够表示部分但不是全部 Unicode 字符的编码。由于String.getBytes()
旨在返回包含要发送到文件或套接字的字节的字节数组,因此该方法需要知道在创建这些字节时应该使用什么编码。基本上,编码必须与稍后读取文件的程序或套接字另一端的计算机所期望的相同。