使用此 link 中给出的以下代码片段,
byte[] bytes = {0x00, 0x48, 0x00, 0x69, 0x00, 0x2C,
0x60, (byte)0xA8, 0x59, 0x7D, 0x00, 0x21}; // "Hi,您好!"
Charset charset = Charset.forName("UTF-8");
// Encode from UCS-2 to UTF-8
// Create a ByteBuffer by wrapping a byte array
ByteBuffer bb = ByteBuffer.wrap(bytes);
// Create a CharBuffer from a view of this ByteBuffer
CharBuffer cb = bb.asCharBuffer();
使用wrap()
方法,“新缓冲区将由给定的字节数组支持”,这里我们没有任何从字节到其他格式的编码,它只是将字节数组放在一个缓冲区。
请你帮我理解一下,当我们在上面的代码中说bb.asCharBuffer()
时,我们到底在做什么?cb
类似于字符数组。因为 char
在 Java 中是 UTF-16,使用 asCharBuffer()
方法,我们是否将 bb
中的每 2bytes 视为 char
?这是正确的方法吗?如果不是,请帮助我采取正确的方法。
编辑: 我尝试了下面 Meisch 推荐的这个程序,
byte[] bytes = {0x00, 0x48, 0x00, 0x69, 0x00, 0x2C,
0x60, (byte)0xA8, 0x59, 0x7D, 0x00, 0x21}; // "Hi,您好!"
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
ByteBuffer bb = ByteBuffer.wrap(bytes);
CharBuffer cb = decoder.decode(bb);
给出异常
Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(Unknown Source)
at java.nio.charset.CharsetDecoder.decode(Unknown Source)
at TestCharSet.main(TestCharSet.java:16)
请帮帮我,我卡在这里!!!
注意:我使用的是 java 1.6
最佳答案
你问:“因为 char
在 Java 中是 UTF-16,使用 asCharBuffer()
方法,我们是否考虑 bb
中的每 2 个字节> 作为 char
?”
这个问题的答案是肯定的。你的理解是正确的。
您的下一个问题是:“这是正确的方法吗?”
如果您只是想演示 ByteBuffer、CharBuffer 和 Charset 类的工作原理,这是可以接受的。
但是,当您编写应用程序时,您永远不会编写那样的代码。首先,不需要字节数组;您可以将字符表示为文字字符串:
String s = "Hi,\u60a8\u597d!";
如果你想将字符串转换为UTF-8字节,你可以简单地这样做:
byte[] encodedBytes = s.getBytes(StandardCharsets.UTF_8);
如果您仍在使用 Java 6,您可以改为这样做:
byte[] encodedBytes = s.getBytes("UTF-8");
更新:您的字节数组代表 UTF-16BE(大端)编码中的字符。具体来说,您的数组每个字符正好有两个字节。这不是有效的 UTF-8 编码字节序列,这就是您收到 MalformedInputException 的原因。
当字符编码为UTF-8字节时,每个字符将用1到4个字节表示。要使您的第二个代码片段正常工作,数组必须是:
byte[] bytes = {
0x48, 0x69, 0x2c, // ASCII chars are 1 byte each
(byte) 0xe6, (byte) 0x82, (byte) 0xa8, // U+60A8
(byte) 0xe5, (byte) 0xa5, (byte) 0xbd, // U+597D
0x21
};
当从字节转换为字符时,我之前的声明仍然适用:您不需要 ByteBuffer 或 CharBuffer 或 Charset 或 CharsetDecoder。您可以使用这些类,但通常只创建一个字符串更简洁:
String s = new String(bytes, "UTF-8");
如果你想要一个 CharBuffer,只需包装字符串:
CharBuffer cb = CharBuffer.wrap(s);
您可能想知道何时适合直接使用 CharsetDecoder。如果字节来自不受您控制的源,并且您有充分的理由相信它可能不包含正确的 UTF-8 编码字节,您就会这样做。使用显式 CharsetDecoder 允许您自定义如何处理无效字节。
关于java - 查询从 "UTF-8"world读取字节到Java "char",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27692989/