Java 2字节中的字符大小不是?

时间:2011-02-22 12:49:25

标签: java string char

我使用RandomAccessFile从文本文件中读取byte

public static void readFile(RandomAccessFile fr) {
    byte[] cbuff = new byte[1];
    fr.read(cbuff,0,1);
    System.out.println(new String(cbuff));
}

为什么我看到一个完整的角色被这个阅读?

8 个答案:

答案 0 :(得分:108)

char表示Java (*)中的字符。它大2个字节(至少是有效值范围所暗示的那个)。

这并不一定意味着字符的每个表示都是2个字节长。实际上,许多编码只为每个字符保留1个字节(或者对于最常见的字符使用1个字节)。

当您调用String(byte[])构造函数时,您要求Java使用平台默认编码将byte[]转换为String。由于平台默认编码通常是1字节编码(如ISO-8859-1)或可变长度编码(如UTF-8),因此可以轻松地将该1字节转换为单个字符。

如果您在使用UTF-16(或UTF-32或UCS-2或UCS-4或...)作为平台默认编码的平台上运行该代码,那么您将无法获得有效结果(您我将获得一个包含Unicode替换字符的String

这是您不应该依赖平台默认编码的原因之一:在byte[]char[] / String之间或InputStream和{{1之间进行转换时或者ReaderOutputStream之间,始终指定要使用的编码。如果不这样做,那么您的代码将取决于平台。

(*)不是完全为真:Writer代表UTF-16代码点。 一个两个 UTF-16代码点代表Unicode代码点。 Unicode代码点通常表示一个字符,但有时会使用多个Unicode代码点来组成一个字符。但上面的近似值足以讨论手头的主题。

答案 1 :(得分:13)

Java将所有内容的“字符”存储为两个字节。但是,当它们成为字符串等时,字节数将取决于您的编码。

某些字符(ASCII)是单字节,但许多其他字符是多字节的。

Java支持Unicode,因此根据:

Java Character Docs

支持的最大值是“\ uFFFF”(十六进制FFFF,十六进制65535)或11111111 11111111二进制(两个字节)。

答案 2 :(得分:6)

构造函数String(byte[] bytes)从缓冲区中获取字节并将它们编码为字符。

它使用平台默认字符集将字节编码为字符。如果您知道,您的文件包含在不同字符集中编码的文本,则可以使用String(byte[] bytes, String charsetName)使用正确的编码(从字节到字符)。

答案 3 :(得分:1)

在ASCII文本文件中,每个字符只有一个字节

答案 4 :(得分:1)

您的文件看起来像包含ASCII字符,只需1个字节即可编码。如果文本文件包含非ASCII字符,例如2字节的UTF-8,那么你只得到第一个字节,而不是整个字符。

答案 5 :(得分:1)

这里有一些很好的答案,但我想指出jvm可以在任意大小的空间中存储一个char值> = 2个字节。

在许多体系结构中,执行未对齐的内存访问会受到惩罚,因此char可能很容易填充到4个字节。甚至可以将volatile char填充到CPU缓存行的大小以防止错误共享。 https://en.wikipedia.org/wiki/False_sharing

对于新的Java程序员来说,字符数组或字符串不仅仅是多个字符可能是不直观的。你应该从"多个字符"中明显地学习和思考字符串和数组。

我还想指出java字符经常被误用。人们没有意识到他们正在编写的代码不能正确处理超过16位的代码点。

答案 6 :(得分:0)

Java按照UTF-16分配2个字节中的2个字符。存储字符时,它最少占用2个字节,最多4个字节。没有1个字节或3个字节的字符存储空间。

答案 7 :(得分:0)

Java 字符为 2 个字节。但是文件编码可能不同。

所以首先你应该知道你的文件使用什么编码。例如,文件可以是 UTF-8 或 ASCII 编码,然后您将通过一次读取一个字节来检索正确的字符。

如果文件的编码是 UTF-16,如果您的 UTF-16 是小端,它可能仍会向您显示正确的字符。例如,A 的小端 UTF-16 是 [65, 0]。然后当你读取第一个字节时,它返回65。第二个字节填充0后,你会得到A。