【问题标题】:convert byte array ending with single null byte to UTF16 encoded string将以单个空字节结尾的字节数组转换为 UTF16 编码字符串
【发布时间】:2017-11-07 12:44:13
【问题描述】:

我得到了一个字节数组,它携带用UCS-2LE编码的字符串,通常UCS-2LE字符串中的空字符串终止符会被编码为两个空字节(00 00),但有时只有一个如下:

import java.nio.charset.Charset;
import java.util.Arrays;

class Ucs {
    public static void main(String[] args) {
        byte[] b = new byte[] {87, 0, 105, 0, 110, 0, 0}; 
        String s = new String(b, Charset.forName("UTF-16LE"));
        System.out.println(Arrays.toString(s.getBytes()));
        System.out.println(s);
    }   
}

这个程序输出

[87、105、110、-17、-65、-67]
赢了。

我不知道为什么字符串的内部字节数组会增长以及未知的 unicode 来自哪里。我怎样才能消除它?

【问题讨论】:

  • getBytes() 使用用户的默认 Java 字符编码,我们不知道,您也可能不知道。尝试使用已知的、有用的 Unicode 字符编码(例如 UTF-16 或 UTF-8)进行转储。
  • “有时只有一个”:你能阻止上游的问题吗?
  • 如果您不喜欢替换字符 (�) 悄悄地指示数据损坏,您可以配置一个字符解码器,改为抛出异常。
  • @TomBlodget 感谢您的提示。上游超出了我的控制,浪费了我的时间!

标签: java string utf-16


【解决方案1】:

忽略最后一个奇数长度的字节会有帮助吗?

int bytesToUse = b.length%2 == 0 ? b.length : b.length - 1;
String s = new String(b, 0, bytesToUse, Charset.forName("UTF-16LE"));

【讨论】:

  • 是的,这是一种方式:)
【解决方案2】:

使用InputStreamReader 以及正确的Charset 或自定义CharsetDecoder

Reader reader = new InputStreamReader(
   new ByteArrayInputStream(new byte[]{87, 105, 110, -17, -65, -67,0,0}),
   Chaset.forName("UTF-16LE"));

Reader reader = new InputStreamReader(
   new ByteArrayInputStream(new byte[]{87, 105, 110, -17, -65, -67,0,0}),
   new CharsetDecoder(Chaset.forName("UTF-16LE"),1,2){
      @Override
      protected CoderResult     decodeLoop(ByteBuffer in, CharBuffer out){
        // detect trailing zero(s) to skip them
        // maybe employ the first version to do actual conversion
      }
   });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多