我必须将字节数组转换为Android中的字符串,但我的字节数组包含负值。

如果我将该字符串再次转换为字节数组,我得到的值与原始字节数组值不同。

我该怎么做才能得到正确的转换?我用来做转换的代码如下:

// Code to convert byte arr to str:
byte[] by_original = {0,1,-2,3,-4,-5,6};
String str1 = new String(by_original);
System.out.println("str1 >> "+str1);

// Code to convert str to byte arr:
byte[] by_new = str1.getBytes();
for(int i=0;i<by_new.length;i++) 
System.out.println("by1["+i+"] >> "+str1);

我被这个问题难住了。


当前回答

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;    

private static String base64Encode(byte[] bytes)
{
    return new BASE64Encoder().encode(bytes);
}

private static byte[] base64Decode(String s) throws IOException
{
    return new BASE64Decoder().decodeBuffer(s);
}

其他回答

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;    

private static String base64Encode(byte[] bytes)
{
    return new BASE64Encoder().encode(bytes);
}

private static byte[] base64Decode(String s) throws IOException
{
    return new BASE64Decoder().decodeBuffer(s);
}

根本问题是(我认为)你在不知不觉中使用了一个字符集:

 bytes != encode(decode(bytes))

在某些情况下。UTF-8就是这样一个字符集的例子。具体来说,某些字节序列在UTF-8中不是有效的编码。如果UTF-8解码器遇到这些序列中的一个,它可能会丢弃违规字节或将它们解码为“没有这样的字符”的Unicode码点。当然,当您尝试将字符编码为字节时,结果将有所不同。

解决方案是:

明确你所使用的字符编码;即使用String构造函数和String。使用显式字符集的toByteArray方法。 为您的字节数据使用正确的字符集…或者选择一个(例如“Latin-1”,其中所有字节序列都映射到有效的Unicode字符。 如果你的字节(真的)是二进制数据,你希望能够通过“基于文本”的通道传输/接收它们,使用像Base64编码…就是为了这个目的设计的。


对于Java,最常见的字符集是Java .nio.charset. standardcharsets。如果您正在编码一个可以包含任何Unicode字符值的字符串,那么建议使用UTF-8编码(UTF_8)。

如果你想在Java中实现1:1的映射,那么你可以使用ISO Latin Alphabet No. 1——通常被称为“Latin 1”或简称为“Latin”(ISO_8859_1)。注意,Java中的Latin-1是Latin-1的IANA版本,它为所有可能的256个值分配字符,包括控制块C0和C1。这些是不可打印的:您不会在任何输出中看到它们。

从Java 8开始,Java包含Java .util。Base64用于Base64编码/解码。对于url安全编码,您可能需要使用Base64。getUrlEncoder代替标准编码器。自Android Oreo(8)以来,这个类也存在于Android中,API级别为26。

使用new String(byOriginal)并使用getBytes()转换回byte[]并不能保证两个byte[]具有相等的值。这是因为调用了StringCoding.encode(..),它会将String编码为Charset.defaultCharset()。在这种编码过程中,编码器可能会选择替换未知字符并进行其他更改。因此,使用String.getBytes()可能不会返回最初传递给构造函数的相等数组。

我们只需要用数组:http://www.mkyong.com/java/how-do-convert-byte-array-to-string-in-java/构造一个新的String

String s = new String(bytes);

结果字符串的字节数取决于所使用的字符集。new String(bytes)和new String(bytes, charset . forname ("utf-8"))和new String(bytes, charset . forname ("utf-16"))在调用String#getBytes()时都将有不同的字节数组(取决于默认字符集)

byte[]和String之间的“正确转换”是显式地声明你想使用的编码。如果你从一个字节[]开始,它实际上不包含文本数据,就没有“适当的转换”。字符串是用于文本的,字节[]是用于二进制数据的,唯一真正明智的做法是避免它们之间的转换,除非你绝对必须这样做。

如果你真的必须使用字符串来保存二进制数据,那么最安全的方法是使用Base64编码。