[英]How do I encode/decode UTF-16LE byte arrays with a BOM?
我需要在java.lang.String
對UTF-16字節數組進行編碼/解碼。 字節數組是通過字節順序標記(BOM)給我的,我需要使用BOM編碼字節數組。
另外,由於我正在與Microsoft客戶端/服務器打交道,因此我希望以小字節序(與LE BOM一起)發出編碼,以避免任何誤解。 我確實意識到,使用BOM可以在大端模式下工作,但是我不想在Windows世界上游。
舉例來說,以下是一種方法,該方法將java.lang.String
編碼為帶有BOM的little endian中的UTF-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)
這是您在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編碼為小端的編碼,我認為即使使用雙重分配,您當前的代碼也不會太糟糕(除非您的字符串確實很可怕)。 如果不是這樣,您可能想做的不是處理字節數組,而是處理java.nio ByteBuffer,並使用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沒有用於帶有BOM的UTF-16LE的內置編碼器。 因此,您必須推出自己的實現。
我最終得到的是:
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.