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

问题描述 投票:0回答:9

我使用

RandomAccessFile
从文本文件中读取
byte

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

为什么我看到它正在读取一个完整的字符?

java string char
9个回答
150
投票

A

char
代表 Java 中的字符 (*)。它有 2 个字节大(或 16 位)。

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

当您调用

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

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

String
)。

这就是为什么您不应该依赖平台默认编码的原因之一:在

byte[]
char[]
/
String
之间或在
InputStream
Reader
之间或在
OutputStream
Writer
之间进行转换时,你应该总是指定哪种编码你想使用。如果不这样做,那么您的代码将依赖于平台。

(*) 这并不完全正确:char 代表一个

UTF-16
代码单元。 onetwo UTF-16 代码单元表示 Unicode 代码点。一个 Unicode 代码点“通常”代表一个字符,但有时使用多个 Unicode 代码点来组成单个字符。但上面的近似值足以讨论当前的主题。 (**) 请注意,在 Android 上,默认字符集始终为 UTF-8

,从 Java 18 开始,Java 平台本身也

切换到此默认值(但仍然可以配置为以旧方式运行) Java 在内部将所有“字符”存储为两个字节。但是,当它们变成字符串等时,字节数将取决于您的编码。


16
投票

Java 支持 Unicode,因此根据:

Java 字符文档

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

构造函数

String(byte[] bytes)

7
投票

它使用平台默认字符集将字节编码为字符。如果您知道您的文件包含以不同字符集编码的文本,您可以使用

String(byte[] bytes, String charsetName)
使用正确的编码(从字节到字符)。

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


2
投票

看起来您的文件包含 ASCII 字符,这些字符仅用 1 个字节进行编码。如果文本文件包含非 ASCII 字符,例如2 字节 UTF-8,那么您只得到第一个字节,而不是整个字符。


1
投票

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


1
投票
https://en.wikipedia.org/wiki/False_sharing

对于新的 Java 程序员来说,字符数组或字符串不仅仅是多个字符可能是不直观的。 您应该将字符串和数组与“多个字符”区分开来学习和思考。 我还想指出java字符经常被误用。 人们没有意识到他们正在编写的代码无法正确处理长度超过 16 位的代码点。

Java 为字符分配 2 个字节中的 2 个,因为它遵循 UTF-16。存储一个字符最少占用2个字节,最多占用4个字节。字符没有1字节或3字节的存储空间。


0
投票

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


0
投票

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

String s = "ABCÃࠁ"; byte[] bytes = s.getBytes(); char[] charArray = s.toCharArray();


0
投票

在上面,字符串enter image description heres中的最后一个字符,也就是

charArray

中的最后一个元素,用3个字节“表示”。如果我们序列化

charArray
,我们会看到以下字节(每个
char
2 个字节)
00 41 00 42 00 43 00 C3 08 01
    

© www.soinside.com 2019 - 2024. All rights reserved.