如何将字节数组转换为字符串,反之亦然?

Jyo*_*sna 228 java

我必须在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);
Run Code Online (Sandbox Code Playgroud)

我陷入了这个问题.

ome*_*dat 350

您的字节数组必须有一些编码.如果您有负值,则编码不能是ASCII.一旦弄明白,就可以使用以下命令将一组字节转换为String:

byte[] bytes = {...}
String str = new String(bytes, "UTF-8"); // for UTF-8 encoding
Run Code Online (Sandbox Code Playgroud)

您可以使用一堆编码,查看Sun javadocs中的Charset类.

  • @UnKnown因为UTF-8将某些字符编码为2或3字节字符串.并非每个字节数组都是有效的UTF-8编码字符串.ISO-8859-1是一个更好的选择:这里每个字符都被编码为一个字节. (12认同)
  • 那只是一个样本,我实际上不知道他应该使用什么编码... (5认同)
  • @MauricePerry你能解释为什么它不适用于`UTF-8`吗? (4认同)
  • 这可能有效,但您应该不惜一切代价避免使用 String 构造函数。 (2认同)
  • 从 Java 1.7 开始,您可以使用 new String(bytes, StandardCharsets.UTF_8) (2认同)

Mic*_*rdt 100

之间的"正确的转换" byte[],并String为明确说明要使用的编码.如果你从a开始byte[]并且它实际上不包含文本数据,则没有 "正确的转换".Strings用于文本,byte[]用于二进制数据,唯一真正明智的做法是避免在它们之间进行转换,除非你绝对不得不这样做.

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

  • Base64,你救了我的命 (4认同)
  • 是的,[字符编码是您必须了解的](http://stackoverflow.com/questions/10611455/what-is-character-encoding)在字符串和字节之间进行转换。 (2认同)
  • Base64编码解决了我的问题.UTF-8不适用于所有输入 (2认同)

Ste*_*n C 37

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

 bytes != encode(decode(bytes))
Run Code Online (Sandbox Code Playgroud)

在某些情况下.UTF-8是这种字符集的一个例子.具体而言,某些字节序列不是UTF-8中的有效编码.如果UTF-8解码器遇到这些序列之一,它可能会丢弃有问题的字节或将它们解码为"无此字符"的Unicode代码点.当然,当您尝试将字符编码为字节时,结果将会不同.

解决方案是:

  1. 明确你正在使用的字符编码; 即使用String.toByteArray带有显式字符集的String构造函数和方法.
  2. 对字节数据使用正确的字符集...或者选择一个(例如"Latin-1",其中所有字节序列都映射到有效的Unicode字符.
  3. 如果您的字节是(实际上)二进制数据,并且您希望能够通过"基于文本"的通道发送/接收它们,请使用类似Base64编码的内容...... 这是为此目的而设计的.


Rav*_*ila 31

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

String s = new String(bytes);
Run Code Online (Sandbox Code Playgroud)

结果字符串的字节根据您使用的字符集而有所不同.新的字符串(字节)和新的字符串(字节,Charset.forName("UTF-8"))和新的字符串(字节,Charset.forName("UTF-16"))都将有不同的字节数组,当你调用字符串# getBytes()(取决于默认的字符集)

  • 否.结果字符串的字节数取决于您使用的字符集.`new String(bytes)`和`new String(bytes,Charset.forName("utf-8"))`和`new String(bytes,Charset.forName("utf-16"))`都将有不同的字节调用`String#getBytes()`时的数组(取决于默认的字符集) (8认同)

sfu*_*ger 12

使用new String(byOriginal)和转换回byte[]使用getBytes()并不能保证两个byte[]具有相同的值.这是由于调用StringCoding.encode(..)将编码StringCharset.defaultCharset().在此编码期间,编码器可能会选择替换未知字符并执行其他更改.因此,使用String.getBytes()可能不会返回一个相同的数组,因为您最初传递给构造函数.


Rup*_*esh 9

为什么会出现问题:正如某人已经指定的那样: 如果以byte []开头并且实际上并不包含文本数据,则没有"正确的转换".字符串用于文本,byte []用于二进制数据,唯一真正明智的做法是避免在它们之间进行转换,除非你绝对不得不这样做.

当我尝试从pdf文件创建byte []然后将其转换为String然后将String作为输入并转换回文件时,我正在观察此问题.

因此,请确保您的编码和解码逻辑与我一样.我明确地将byte []编码为Base64并对其进行解码以再次创建文件.

使用情况: 由于一些限制,我是想发送byte[]request(POST),过程如下:

PDF文件>> Base64.encodeBase64(byte [])>> String >>发送请求(POST)>>接收字符串>> Base64.decodeBase64(byte [])>>创建二进制

试试这个,这对我有用..

File file = new File("filePath");

        byte[] byteArray = new byte[(int) file.length()];

        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            fileInputStream.read(byteArray);

            String byteArrayStr= new String(Base64.encodeBase64(byteArray));

            FileOutputStream fos = new FileOutputStream("newFilePath");
            fos.write(Base64.decodeBase64(byteArrayStr.getBytes()));
            fos.close();
        } 
        catch (FileNotFoundException e) {
            System.out.println("File Not Found.");
            e.printStackTrace();
        }
        catch (IOException e1) {
            System.out.println("Error Reading The File.");
            e1.printStackTrace();
        }
Run Code Online (Sandbox Code Playgroud)

  • 这是否使用外部库,例如 Apache 编解码器?如果是这样**请在答案中指出**。 (2认同)

Shi*_*yya 7

以下是将字节数组安全地转换为字符串以及将字符串安全地转换回字节数组的示例代码。

 byte bytesArray[] = { 1, -2, 4, -5, 10};
 String encoded = java.util.Base64.getEncoder().encodeToString(bytesArray);
 byte[] decoded = java.util.Base64.getDecoder().decode(encoded);
 System.out.println("input: "+Arrays.toString(bytesArray));
 System.out.println("encoded: "+encoded);
 System.out.println("decoded: "+Arrays.toString(decoded));
Run Code Online (Sandbox Code Playgroud)

输出:

input: [1, -2, 4, -5, 10]
encoded: Af4E+wo=
decoded: [1, -2, 4, -5, 10]
Run Code Online (Sandbox Code Playgroud)


小智 6

这对我来说很好:

String cd="Holding some value";
Run Code Online (Sandbox Code Playgroud)

从字符串转换为字节[]:

byte[] cookie = new sun.misc.BASE64Decoder().decodeBuffer(cd);
Run Code Online (Sandbox Code Playgroud)

从byte []转换为string:

cd = new sun.misc.BASE64Encoder().encode(cookie);
Run Code Online (Sandbox Code Playgroud)


gil*_*des 6

虽然

new String(bytes, "UTF-8")
Run Code Online (Sandbox Code Playgroud)

是正确的,它会抛出 aUnsupportedEncodingException迫使您处理已检查的异常。您可以使用自 Java 1.6 以来的另一种构造函数将字节数组转换为String

new String(bytes, StandardCharsets.UTF_8)
Run Code Online (Sandbox Code Playgroud)

这个不会抛出任何异常。

转换回来也应该完成StandardCharsets.UTF_8

"test".getBytes(StandardCharsets.UTF_8)
Run Code Online (Sandbox Code Playgroud)

再次,您不必处理已检查的异常。

  • 这是一个很好的评论,但是使用 new String 本身就不好,所以它不能解决根本问题。 (2认同)

sde*_*e57 5

private static String toHexadecimal(byte[] digest){
        String hash = "";
    for(byte aux : digest) {
        int b = aux & 0xff;
        if (Integer.toHexString(b).length() == 1) hash += "0";
        hash += Integer.toHexString(b);
    }
    return hash;
}
Run Code Online (Sandbox Code Playgroud)


Leo*_*nid 5

我确实注意到任何答案都没有的东西.您可以将字节数组中的每个字节转换为字符,并将它们放在char数组中.然后是字符串

new String(cbuf)
Run Code Online (Sandbox Code Playgroud)其中cbuf是char数组.要转换回来,循环遍历字符串,将每个字符转换为字节以放入字节数组,并且此字节数组将与第一个字节数组相同.


public class StringByteArrTest {

    public static void main(String[] args) {
        // put whatever byte array here
        byte[] arr = new byte[] {-12, -100, -49, 100, -63, 0, -90};
        for (byte b: arr) System.out.println(b);
        // put data into this char array
        char[] cbuf = new char[arr.length];
        for (int i = 0; i < arr.length; i++) {
            cbuf[i] = (char) arr[i];
        }
        // this is the string
        String s = new String(cbuf);
        System.out.println(s);

        // converting back
        byte[] out = new byte[s.length()];
        for (int i = 0; i < s.length(); i++) {
            out[i] = (byte) s.charAt(i);
        }
        for (byte b: out) System.out.println(b);
    }

}

Run Code Online (Sandbox Code Playgroud)