当i/o流管理8位字节的原始二进制数据时,它被称为字节流。而且,当i/o流管理16位unicode字符时,它被称为字符流。 Byte stream
很清楚。它使用8位字节。所以如果我要写一个使用3字节的字符,它只会写最后8位!从而产生不正确的输出。
所以我们用 character streams
. 说我想写拉丁文大写字母 Ạ
. 我需要3个字节来存储在utf-8中。但如果我也想储存“正常” A
. 现在需要1个字节来存储!
你看到模式了吗?在转换这些字符之前,我们不知道写这些字符需要多少字节。所以我的问题是为什么会这么说 character streams manage 16-bit Unicode characters
? 万一我写了什么 Ạ
这需要3个字节,它没有像这样把它压缩到最后16位 byte streams
切最后8位。那句话是什么意思?
2条答案
按热度按时间rn0zuynd1#
在java语言中,字符(
char
)总是16位,从它的最大值65535可以看出。这就是为什么报价没有错。16位确实是一个字符。您可能会问:“如何将所有unicode字符仅存储在16位中?”。这是在java中使用utf-16编码完成的。下面是它的工作原理(非常简单):
基本多语言平面中的每个unicode码位都用16位编码(是的,16位就足够了)bmp之外的每个代码点都用一对16位字符编码,称为代理项对。
"ạ" (u+1ea0)位于bmp内部,因此可以用16位进行编码。
你说:
说我想写拉丁文大写字母ạ. 我需要3个字节来存储在utf-8中。但假设我也想存储“正常”a。现在需要1个字节来存储!
但这并不意味着报价不正确。流仍然“管理16位字符”,因为这是您将用java代码提供的。当你打电话的时候
println
在PrintStream
,你在给它一个String
,这是一堆char
它在引擎盖下,是一堆16比特。所以它实际上是在管理一个16位字符流。只是它以不同的编码输出它们。可能值得一提的是,当您尝试打印bmp中没有的字符时会发生什么。这仍然不会使报价不正确。引用没有说“代码点”。它表示“character”,它将引用您正在打印的代理项对的上/下代理项。
gc0ot86w2#
在java中,一个
String
由16位的序列组成char
s、 表示存储在utf-16编码中的文本。一
Charset
描述如何将unicode字符转换为字节序列的对象。utf-8是字符集的一个例子。像这样的字符流
Writer
,当它输出到一个包含字节的东西时--一个文件,或者一个字节输出流,比如OutputStream
--使用Charset
转换String
s到简单的字节序列输出(从技术上讲,它将utf-16字符转换为unicode字符,然后使用Charset
)aReader
,从字节源读取时,执行反向转换。在utf-16中,ạ 表示为16位
char
0x1EA1
. 在utf-16中它只需要16位,而不像在utf-8中需要24位。如果使用utf-8编码将其转换为字节,如下所示:
然后您将得到3字节序列0xe10xba0xa1。