为什么说:CharacterStream类是用来执行16位Unicode字符的input/output?
Why is it said: CharacterStream classes are used to perform the input/output for the 16-bit Unicode characters?
When an I/O stream manages 8-bit bytes of raw binary data, it is
called a byte stream. And, when the I/O stream manages 16-bit Unicode
characters, it is called a character stream.
Byte stream
清楚了。它使用 8 位字节。所以如果我要写一个 character 使用 3 bytes 它只会写它的最后 8 bits !从而使输出不正确。
所以这就是我们使用 character streams
的原因。假设我想写拉丁文大写字母 Ạ
。我需要 3 个字节 来以 UTF-8 格式存储。但是说我也想存储'normal'A
。现在需要 1 个字节 来存储。
你看到规律了吗?在我们转换它们之前,我们无法知道写入任何这些 字符 需要多少字节。所以我的问题是为什么说character streams manage 16-bit Unicode characters
?如果我写的 Ạ
需要 3 个字节 ,它不会像 [=18] 那样将其削减到 最后 16 位 =] 剪切最后 8 位 。那句话到底是什么意思?
在Java中,一个String
是由一个16位的char
序列组成的,表示以UTF-16编码存储的文本。
A Charset
是描述如何将 Unicode 字符转换为字节序列的对象。 UTF-8 是字符集的一个例子。
一个像Writer
这样的字符流,当它输出到一个包含字节的东西——一个文件,或者一个像OutputStream
这样的字节输出流——使用一个Charset
来将 String
s 转换为简单的字节序列以进行输出。 (从技术上讲,它将 UTF-16 字符转换为 Unicode 字符,然后使用 Charset
将它们转换为字节序列。)从字节源读取时,Reader
执行反向转换。
在UTF-16中,Ạ表示为16位char
0x1EA1
。它在 UTF-16 中只需要 16 位,而不是像在 UTF-8 中那样需要 24 位。
如果您将它转换为使用 UTF-8 编码的字节,如下所示:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(baos, StandardCharsets.UTF_8);
writer.write("Ạ");
writer.close();
return baos.toByteArray();
然后你会得到预期的 3 字节序列 0xE1 0xBA 0xA1。
在Java中,一个字符(char
)总是16位,从它的最大值可以看出——65535。这就是引号没有错的原因。 16位是确实是一个字符
“如何将所有 Unicode 字符存储在 16 位中?”你可能会问。这是在 Java 中使用 UTF-16 编码完成的。这是它的工作原理(用非常简单的术语):
基本多语言平面中的每个 Unicode 代码点都以 16 位编码。 (是的,16 位就足够了)BMP 之外的每个代码点都用一对 16 位字符编码,称为代理对。
"Ạ" (U+1EA0) 在BMP中,所以可以用16位编码。
你说:
Say I want to write Latin Capital Letter Ạ. I would need 3 bytes for storing in UTF-8. But say I also want to store 'normal' A. Now it would take 1 byte to store!
这并没有使引用不正确。该流仍然“管理 16 位字符”,因为这是您将使用 Java 代码赋予它的内容。当你在 PrintStream
上调用 println
时,你给它一个 String
,它是引擎盖下的一堆 char
,这是一堆 16 位.所以它实际上是在管理一个 16 位字符流。只是它以不同的编码输出它们。
可能值得一提的是当您尝试打印不在 BMP 中的字符时会发生什么。这仍然不会使报价不正确。报价没有说“代码点”。它说“字符”,它指的是您正在打印的代理对的 upper/lower 代理。
When an I/O stream manages 8-bit bytes of raw binary data, it is called a byte stream. And, when the I/O stream manages 16-bit Unicode characters, it is called a character stream.
Byte stream
清楚了。它使用 8 位字节。所以如果我要写一个 character 使用 3 bytes 它只会写它的最后 8 bits !从而使输出不正确。
所以这就是我们使用 character streams
的原因。假设我想写拉丁文大写字母 Ạ
。我需要 3 个字节 来以 UTF-8 格式存储。但是说我也想存储'normal'A
。现在需要 1 个字节 来存储。
你看到规律了吗?在我们转换它们之前,我们无法知道写入任何这些 字符 需要多少字节。所以我的问题是为什么说character streams manage 16-bit Unicode characters
?如果我写的 Ạ
需要 3 个字节 ,它不会像 [=18] 那样将其削减到 最后 16 位 =] 剪切最后 8 位 。那句话到底是什么意思?
在Java中,一个String
是由一个16位的char
序列组成的,表示以UTF-16编码存储的文本。
A Charset
是描述如何将 Unicode 字符转换为字节序列的对象。 UTF-8 是字符集的一个例子。
一个像Writer
这样的字符流,当它输出到一个包含字节的东西——一个文件,或者一个像OutputStream
这样的字节输出流——使用一个Charset
来将 String
s 转换为简单的字节序列以进行输出。 (从技术上讲,它将 UTF-16 字符转换为 Unicode 字符,然后使用 Charset
将它们转换为字节序列。)从字节源读取时,Reader
执行反向转换。
在UTF-16中,Ạ表示为16位char
0x1EA1
。它在 UTF-16 中只需要 16 位,而不是像在 UTF-8 中那样需要 24 位。
如果您将它转换为使用 UTF-8 编码的字节,如下所示:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(baos, StandardCharsets.UTF_8);
writer.write("Ạ");
writer.close();
return baos.toByteArray();
然后你会得到预期的 3 字节序列 0xE1 0xBA 0xA1。
在Java中,一个字符(char
)总是16位,从它的最大值可以看出——65535。这就是引号没有错的原因。 16位是确实是一个字符
“如何将所有 Unicode 字符存储在 16 位中?”你可能会问。这是在 Java 中使用 UTF-16 编码完成的。这是它的工作原理(用非常简单的术语):
基本多语言平面中的每个 Unicode 代码点都以 16 位编码。 (是的,16 位就足够了)BMP 之外的每个代码点都用一对 16 位字符编码,称为代理对。
"Ạ" (U+1EA0) 在BMP中,所以可以用16位编码。
你说:
Say I want to write Latin Capital Letter Ạ. I would need 3 bytes for storing in UTF-8. But say I also want to store 'normal' A. Now it would take 1 byte to store!
这并没有使引用不正确。该流仍然“管理 16 位字符”,因为这是您将使用 Java 代码赋予它的内容。当你在 PrintStream
上调用 println
时,你给它一个 String
,它是引擎盖下的一堆 char
,这是一堆 16 位.所以它实际上是在管理一个 16 位字符流。只是它以不同的编码输出它们。
可能值得一提的是当您尝试打印不在 BMP 中的字符时会发生什么。这仍然不会使报价不正确。报价没有说“代码点”。它说“字符”,它指的是您正在打印的代理对的 upper/lower 代理。