有了此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()方法,“新的缓冲区将由给定的字节数组支持”,这里我们没有从字节到其他格式的任何编码,它只是将字节数组放在缓冲区中.
cb与字符数组相似时,请您帮我理解,当我们在上面的代码中说bb.asCharBuffer()时,我们到底在做什么?由于char在Java中是UTF-16,因此使用asCharBuffer()方法,我们是否会将bb中的每2个字节视为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
};
从字节转换为char时,我的先前声明仍然适用:您不需要ByteBuffer或CharBuffer或Charset或CharsetDecoder.您可以使用这些类,但是通常创建一个String更为简洁:
String s = new String(bytes, "UTF-8");
如果需要CharBuffer,只需包装字符串:
CharBuffer cb = CharBuffer.wrap(s);
您可能想知道什么时候适合直接使用CharsetDecoder.如果这些字节来自不受您控制的源,并且您有充分的理由相信它可能不包含正确的UTF-8编码字节,则可以这样做.使用显式的CharsetDecoder可让您自定义如何处理无效字节.