如何使用 BOM 对 UTF-16LE 字节数组进行编码/解码?

2022-09-01 20:22:47

我需要将 UTF-16 字节数组编码/解码为 /字节数组是用字节顺序标记(BOM)给我的,我需要用BOM编码字节数组。java.lang.String

另外,由于我正在处理Microsoft客户端/服务器,因此我想以小端序(以及LE BOM)发出编码以避免任何误解。我确实意识到,使用BOM,它应该可以工作在大端序,但我不想在Windows世界中上游游走。

例如,下面是一个使用 BOM 对小端序中的 as 进行编码的方法:java.lang.StringUTF-16

public static byte[] encodeString(String message) {

    byte[] tmp = null;
    try {
        tmp = message.getBytes("UTF-16LE");
    } catch(UnsupportedEncodingException e) {
        // should not possible
        AssertionError ae =
        new AssertionError("Could not encode UTF-16LE");
        ae.initCause(e);
        throw ae;
    }

    // use brute force method to add BOM
    byte[] utf16lemessage = new byte[2 + tmp.length];
    utf16lemessage[0] = (byte)0xFF;
    utf16lemessage[1] = (byte)0xFE;
    System.arraycopy(tmp, 0,
                     utf16lemessage, 2,
                     tmp.length);
    return utf16lemessage;
}

在Java中做到这一点的最佳方法是什么?理想情况下,我希望避免将整个字节数组复制到一个新的字节数组中,该数组在开始时分配了两个额外的字节。

解码这样的字符串也是如此,但是通过使用java.lang.String构造函数,这要简单得多:

public String(byte[] bytes,
              int offset,
              int length,
              String charsetName)

答案 1

“UTF-16”字符集名称将始终使用 BOM 进行编码,并将使用大/小字节序对数据进行解码,但“UnicodeBig”和“UnicodeLittle”对于按特定字节顺序进行编码很有用。使用 UTF-16LE 或 UTF-16BE 无需 BOM - 有关如何使用“\uFEFF”手动处理 BOM 的信息,请参阅此文章。有关字符集字符串名称的规范命名或(最好是 Charset 类),请参阅此处。另请注意,绝对只需要支持有限的编码子集


答案 2

首先,对于解码,您可以使用字符集“UTF-16”;自动检测初始物料清单。对于 UTF-16BE 编码,您还可以使用“UTF-16”字符集 - 这将编写适当的 BOM,然后输出大端。

对于使用BOM编码为小字节序,我认为您当前的代码不会太糟糕,即使使用双重分配也是如此(除非您的字符串确实很糟糕)。如果它们是,你可能想做的不是处理一个字节数组,而是一个java.nio ByteBuffer,并使用java.nio.charset.CharsetEncoder类(你可以从Charset.forName(“UTF-16LE”).newEncoder())获得)。


推荐