将字节数组转换为字符串(Java)

Posted

技术标签:

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

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

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

这是我现在唯一的问题:

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

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

【问题讨论】:

重复***.com/questions/1536054/… 嗨,我知道这是一篇很老的帖子,但我也面临着类似的问题。我正在为 ssl 做一个中间人代理。我面临的问题和你的一样。我监听套接字并将数据输入InputStream,然后输入byte[]。现在,当我尝试将byte[] 转换为字符串(我需要使用响应体进行攻击)时,我得到了非常有趣的字符,其中充满了智能引号和问号等等。我相信你的问题和我的一样,因为我们都在处理byte[] 中的html。可以请教吗? 顺便说一句,我用 Sytem.properties 找到了我系统的编码,发现它是“Cp1252”。现在,我使用了String str=new String(buffer, "Cp1252");,但没有任何帮助。 What is character encoding and why should I bother with it的可能重复 【参考方案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 及以上版本

您还可以将所需的编码作为来自StandardCharsets 的Charset 常量传递给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。

【讨论】:

以上是关于将字节数组转换为字符串(Java)的主要内容,如果未能解决你的问题,请参考以下文章

如何在Java中将二维布尔数组转换为一维字节数组?

Java题目:编写程序,将一个字符串转为字节数组输入流。转换为大写字母输出。

将奇数长度的java字符串转换为十六进制字节数组

在java中将字符串数组元素转换为字节数组[重复]

C 字节数组转换成字符串

将字节数组转换为String(Java)