Java 2字节中的字符大小不?
我使用RandomAccessFile
从文本文件中读取一个byte
。
public static void readFile(RandomAccessFile fr) { byte[] cbuff = new byte[1]; fr.read(cbuff,0,1); System.out.println(new String(cbuff)); }
为什么我看到一个完整的字符被读取?
char
代表Java (*)中的字符。 它是2个字节大(至less这是有效值范围build议)。
这并不一定意味着每个字符的表示都是2个字节。 事实上,许多编码只为每个字符保留1个字节(或者对于最常见的字符使用1个字节)。
在调用String(byte[])
构造函数时,要求Java使用平台默认编码将byte[]
转换为String
。 由于平台的默认编码通常是一个1字节的编码,比如ISO-8859-1或者一个可变长度的编码,比如UTF-8,所以它可以很容易地把这个1字节转换成一个字符。
如果您在使用UTF-16(或UTF-32或UCS-2或UCS-4或…)的平台上运行该代码作为平台默认编码,那么您将无法获得有效的结果一个包含Unicodereplace字符的String
)。
这就是为什么你不应该依赖平台默认编码的原因之一:在byte[]
和char[]
/ String
之间转换时,或者在InputStream
和Reader
之间或OutputStream
和Writer
之间转换时,应该总是指定要使用的编码。 如果你不这样做,那么你的代码将取决于平台。
(*)并不完全正确: char
表示一个UTF-16码点。 一个或两个 UTF-16码点表示一个Unicode码点。 一个Unicode代码点通常代表一个字符,但是有时候会使用多个Unicode代码点来组成单个字符。 但是上面的近似值足以讨论手头的话题。
Java在内部将所有的“字符”存储为两个字节。 但是,当它们变成string等时,字节数将取决于您的编码。
有些字符(ASCII)是单字节,但是其他字符是多字节。
Java支持Unicode,因此根据:
Java字符文件
支持的最大值是“\ uFFFF”(hexFFFF,分辨率65535)或11111111 11111111二进制(两个字节)。
构造函数String(byte[] bytes)
从缓冲区获取字节并将其编码为字符。
它使用平台默认字符集将字节编码为字符。 如果您知道,您的文件包含文本,即以不同的字符集进行编码,则可以使用String(byte[] bytes, String charsetName)
来使用正确的编码(从字节到字符)。
在ASCII文本文件中,每个字符只是一个字节
看起来像你的文件包含ASCII字符,这是在一个字节编码。 如果文本文件包含非ASCII字符,例如2字节的UTF-8,那么您只得到第一个字节,而不是整个字符。
这里有一些很好的答案,但我想指出,jvm可以在任何大小的空间> = 2个字节中自由地存储char值。
在许多体系结构中,执行未alignment的内存访问是一个惩罚,所以char可以很容易地填充到4个字节。 易失字符甚至可能被填充到CPUcaching行的大小以防止错误共享。 https://en.wikipedia.org/wiki/False_sharing
对于新的Java程序员来说,字符数组或string不仅仅是多个字符可能是不直观的。 您应该从“多个字符”中清楚地学习和思考string和数组。
我也想指出,Java字符经常被滥用。 人们没有意识到他们正在编写的代码不能正确处理长度超过16位的代码点。