如何使用 BOM 对 UTF-16LE 字节数组进行编码/解码?
-
22-08-2019 - |
题
我需要对 UTF-16 字节数组进行编码/解码 java.lang.String
. 。字节数组是通过一个给我的 字节顺序标记 (BOM), ,并且我需要使用 BOM 对字节数组进行编码。
另外,因为我正在处理 Microsoft 客户端/服务器,所以我想以小尾数法(以及 LE BOM)发出编码以避免任何误解。我确实意识到,对于 BOM,它应该以大端方式工作,但我不想在 Windows 世界中逆流而上。
作为一个例子,这是一个编码的方法 java.lang.String
作为 UTF-16
带有 BOM 的小端字节序:
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)
其他提示
这是你如何在NIO做到这一点:
return Charset.forName("UTF-16LE").encode(message)
.put(0, (byte) 0xFF)
.put(1, (byte) 0xFE)
.array();
这当然应该是快,但我不知道有多少阵列使得在幕后,但是我的API点的理解是,它应该尽量减少。
首先,用于解码可使用的字符集“UTF-16”;自动检测的初始BOM。对于编码UTF-16BE,您还可以使用“UTF-16”字符集 - 那会写一个正确的BOM,然后输出大端东西
。有关编码为小端与BOM,我不认为你当前的代码是太糟糕了,即使有双重分配(除非你的字符串是真正可怕的)。你可能会想,如果他们不处理的字节数组,而是一个ByteBuffer的java.nio中,并使用java.nio.charset.CharsetEncoder类的事情。 (你可以从Charset.forName( “UTF-16LE”)。newEncoder())。
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(string.length() * 2 + 2);
byteArrayOutputStream.write(new byte[]{(byte)0xFF,(byte)0xFE});
byteArrayOutputStream.write(string.getBytes("UTF-16LE"));
return byteArrayOutputStream.toByteArray();
编辑:重读你的问题,我看你宁愿避免双重数组分配完全。不幸的是,API不给你的是,据我所知。 (有一种方法,但它已被弃用,则不能指定与它的编码)。
我写上面之前我看到你的评论,我想用NIO类的答案是正确的轨道上。我看着这一点,但我不熟悉不够用API知道了手如何弄完。
这是一个老问题了,不过,我找不到我的情况可以接受的答案。基本上,Java没有为UTF-16LE以BOM内置编码器。所以,你必须推出自己的实现。
这是我结束了:
private byte[] encodeUTF16LEWithBOM(final String s) {
ByteBuffer content = Charset.forName("UTF-16LE").encode(s);
byte[] bom = { (byte) 0xff, (byte) 0xfe };
return ByteBuffer.allocate(content.capacity() + bom.length).put(bom).put(content).array();
}