【问题标题】:Does Java's String.getBytes("ISO-8859-1") return the first byte of each 2-byte character in a string?Java 的 String.getBytes("ISO-8859-1") 是否返回字符串中每个 2 字节字符的第一个字节?
【发布时间】:2011-08-05 20:20:15
【问题描述】:

我认为 UCS-2 到 ISO-8859-1 是一样的

    rawData = new byte[data.length()];
    for(int i=0; i<data.length(); i++) {
        rawData[i] = (byte)(data.charAt(i) & 0xff);
    }

这似乎是错误的。为什么上面的代码不等同于data.getBytes("ISO8859_1")?我在 Android 上。

事实上,我的一些角色是0xf700 &amp; (byte)。出于某种原因,当您使用XMLHttpRequestCharset: x-user-defined 获取二进制文件时会发生这种情况。当转换为latin1 时,这些字符会变成?(问号)。

【问题讨论】:

    标签: java android unicode


    【解决方案1】:

    通过安卓documentation:

    未指定此字符串无法在命名字符集中表示时的行为。

    在实践中,这个调用最终会成为一个带有显式Charset 的变体,它将用一些替换序列替换不可翻译的字符。在 Sun JDK 中,这是一个单字节值 64('?')。

    但是,在您对先前答案的评论中,您保证字符串中没有大于“0xFF”的字符值,那么您做错了什么。 ISO-8859-1 是 UCS-2/UTF-16 的真子集。

    【讨论】:

    • 不,如果字符串在由UTF-16ISO-8859-1 编码时产生相同的字节,这将是一个“正确的子集”,显然不是。
    • 我可能做错了什么。我将通过比较两种不同方法的两个字节 [] 来仔细检查。
    【解决方案2】:

    parsifal 的回答已经解释了原因。为了完整起见,这里是相当于data.getBytes("ISO-8859-1") 的代码(假设字符串是纯UCS-2 字符串,没有代理对):

    byte[] rawdata = new byte[data.length()];
    for(int i = 0; i < data.length; i++) {
        char c = data.charAt(i);
        if (c > 255) {
            rawData[i] = (byte)'?';
        }
        else {
            rawData[i] = (byte)c;
        }
    }
    

    使用代理(例如真正的 UTF-16)会变得有点复杂:

    byte[] rawData = new byte[data.length()];
    int j = 0;
    for(int i = 0; i < data.length; i++, j++) {
        int c = data.codePointAt(i);
        if(c < 0x100) {
            rawData[j] = (byte)c;
        }
        else {
            rawData[j] = (byte)'?';
            if(c >= 0x10000) {
               // surrogate pair
               i++;
            }
        }
    }
    if(j < rawData.length) {
       rawData = Arrays.copyOf(rawData, j);
    }
    

    或者,只使用charAt()

    byte[] rawData = new byte[data.length()];
    int j = 0;
    for(int i = 0; i < data.length; i++, j++) {
        char c = data.charAt(i);
        if(c < 0x100) {
            rawData[j] = (byte)c;
        }
        else {
            rawData[j] = (byte)'?';
            if(Character.isHighSurrogate(c) && Character.isLowSurrogate(data.charAt(i+1))) {
               // surrogate pair
               i++;
            }
        }
    }
    if(j < rawData.length) {
       rawData = Arrays.copyOf(rawData, j);
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-25
      • 2011-08-24
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多