查询从“ UTF-8”世界到Java“ char”的读取字节

有了此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可让您自定义如何处理无效字节.

上一篇:Java 范例 - 字节处理


下一篇:Java-ByteBuffer或ArrayList?