【问题标题】:Converting byte array to String (Java)将字节数组转换为字符串(Java)
【发布时间】:2011-08-06 02:16:49
【问题描述】:

我正在 Google 应用引擎中编写一个网络应用程序。它允许人们基本上编辑在 blobstore 中存储为 .html 文件的 html 代码。

我正在使用 fetchData 返回文件中所有字符的byte[]。我正在尝试打印到 html 以便用户编辑 html 代码。一切都很好!

这是我现在唯一的问题:

字节数组在转换回字符串时出现一些问题。智能引号和几个字符看起来很时髦。 (?的或日文符号等)具体来说,我看到的几个字节具有导致问题的负值。

智能引号在字节数组中返回为-108-109。为什么会这样?如何解码负字节以显示正确的字符编码?

【问题讨论】:

  • 嗨,我知道这是一篇很老的帖子,但我也面临着类似的问题。我正在为 ssl 做一个中间人代理。我面临的问题和你的一样。我监听套接字并将数据输入InputStream,然后输入byte[]。现在,当我尝试将byte[] 转换为字符串(我需要使用响应体进行攻击)时,我得到了非常有趣的字符,其中充满了智能引号和问号等等。我相信你的问题和我的一样,因为我们都在处理byte[] 中的html。可以请教吗?
  • 顺便说一句,我用 Sytem.properties 找到了我系统的编码,发现它是“Cp1252”。现在,我使用了String str=new String(buffer, "Cp1252");,但没有任何帮助。

标签: java google-app-engine character-encoding bytearray


【解决方案1】:

字节数组包含特殊编码的字符(您应该知道)。转成String的方法是:

String decoded = new String(bytes, "UTF-8");  // example for one encoding type

顺便说一下 - 出现的原始字节可能显示为负小数,因为 java 数据类型 byte 是有符号的,它涵盖了从 -128 到 127 的范围。


-109 = 0x93: Control Code "Set Transmit State"

值 (-109) 是 UNICODE 中不可打印的控制字符。所以 UTF-8 不是该字符流的正确编码。

“Windows-1252”中的0x93 是您正在寻找的“智能引用”,因此该编码的Java 名称是“Cp1252”。下一行提供了一个测试代码:

System.out.println(new String(new byte[]{-109}, "Cp1252")); 

【讨论】:

  • 我尝试使用 UTF-8,但它仍然显示为 ?'s。为什么没有找到那些负值的映射?
  • 0x93 在 UTF-8 中是一个有效的连续字节,但是 - 如果它没有出现在设置了前两位的字节之后,那么该字节的存在只会排除它是 UTF-8。
  • @Josh Andreas 解释了原因 - 因为 Java 的 byte 数据类型已签名。 “负”值只是具有最高有效字节集的字节。他还解释了您应该使用的最可能的字符集是 Windows-1252。不过,您应该从上下文或约定中知道要使用什么字符集,而不必猜测。
【解决方案2】:

Java 7 及以上版本

您还可以将所需的编码作为来自StandardCharsetsCharset 常量传递给String 构造函数。正如其他答案中所建议的那样,这可能比将编码作为String 传递更安全。

例如,对于 UTF-8 编码

String bytesAsString = new String(bytes, StandardCharsets.UTF_8);

【讨论】:

  • 这是 2011 年答案的重复。-1
  • @james.garriss 我不认为是这样,因为我只是提到了 java 7 中引入的一个新构造函数,它允许将编码作为常量传递,我认为这更好,并且比之前的答案中提到的以前的 api 更安全,其中编码作为字符串传递,如果有的话。
【解决方案3】:

你可以试试这个。

String s = new String(bytearray);

【讨论】:

  • 您可以尝试...但几乎在所有情况下都会失败。
【解决方案4】:
public class Main {

    /**
     * Example method for converting a byte to a String.
     */
    public void convertByteToString() {

        byte b = 65;

        //Using the static toString method of the Byte class
        System.out.println(Byte.toString(b));

        //Using simple concatenation with an empty String
        System.out.println(b + "");

        //Creating a byte array and passing it to the String constructor
        System.out.println(new String(new byte[] {b}));

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Main().convertByteToString();
    }
}

输出

65
65
A

【讨论】:

    【解决方案5】:
    public static String readFile(String fn)   throws IOException 
    {
        File f = new File(fn);
    
        byte[] buffer = new byte[(int)f.length()];
        FileInputStream is = new FileInputStream(fn);
        is.read(buffer);
        is.close();
    
        return  new String(buffer, "UTF-8"); // use desired encoding
    }
    

    【讨论】:

    • 如果read 抛出异常,此代码将泄漏资源。
    【解决方案6】:

    我建议Arrays.toString(byte_array);

    这取决于你的目的。例如,我想保存一个字节数组,就像您在调试时可以看到的格式一样:[1, 2, 3] 如果您想保存完全相同的值而不将字节转换为字符格式,Arrays.toString (byte_array) 可以这,。但是如果你想保存字符而不是字节,你应该使用String s = new String(byte_array)。在这种情况下,s 等价于字符格式的[1, 2, 3]

    【讨论】:

    • 您能否提供更多信息,说明您为什么建议这样做? (能解决问题吗?能说一下为什么能解决吗?)谢谢!
    • 这取决于你的目的。例如,我想保存一个字节数组,就像您在调试时可以看到的格式一样: [1, 2, 3] 如果您想保存完全相同的值而不将字节转换为字符格式, Arrays.toString (byte_array) 就是这样做的。但是如果你想保存字符而不是字节,你应该使用 String s = new String(byte_array)。在这种情况下,s 等价于字符格式的 [1, 2, 3]。
    • @sas,您应该将此信息添加到您的答案本身(通过编辑它)而不是作为评论。通常在 SO 上,您应该始终牢记 cmets 可能随时被删除 - 真正重要的信息应该在答案本身中。
    【解决方案7】:

    Andreas_D 之前的回答很好。我只是要补充一点,无论你在哪里显示输出,都会有一个字体和一个字符编码,它可能不支持某些字符。

    要确定是 Java 还是您的显示器有问题,请执行以下操作:

        for(int i=0;i<str.length();i++) {
            char ch = str.charAt(i);
            System.out.println(i+" : "+ch+" "+Integer.toHexString(ch)+((ch=='\ufffd') ? " Unknown character" : ""));
        }
    

    Java 会将它无法理解的任何字符映射到 0xfffd 未知字符的官方字符。如果你看到一个“?”在输出中,但它没有映射到 0xfffd,这是您的显示字体或编码问题,而不是 Java。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-19
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      相关资源
      最近更新 更多