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

时间:2009-10-08 07:01:35

标签: 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);

我遇到了这个问题。

24 个答案:

答案 0 :(得分:324)

您的字节数组必须有一些编码。如果您有负值,则编码不能是ASCII。一旦弄明白,就可以使用:

将一组字节转换为String
byte[] bytes = {...}
String str = new String(bytes, "UTF-8"); // for UTF-8 encoding

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

答案 1 :(得分:98)

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

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

答案 2 :(得分:36)

根本问题是(我认为)您无意中使用了以下字符集:

 bytes != encode(decode(bytes))

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

解决方案是:

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

答案 3 :(得分:31)

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

String s = new String(bytes);

结果字符串的字节根据您使用的字符集而有所不同。调用String#时,新的String(字节)和新的String(字节,字符串,Charset.forName(“utf-8”))和新的字符串(字节,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字节数getBytes()(取决于默认字符集)

答案 4 :(得分:12)

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

答案 5 :(得分:9)

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

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

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

使用情况: 由于某些限制,我尝试在byte[]中发送request(POST),过程如下:

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

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

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();
        }

答案 6 :(得分:6)

这对我来说很好用:

String cd="Holding some value";

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

byte[] cookie = new sun.misc.BASE64Decoder().decodeBuffer(cd);

从byte []转换为string:

cd = new sun.misc.BASE64Encoder().encode(cookie);

答案 7 :(得分:5)

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

new String(cbuf)
,其中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);
    }

}

答案 8 :(得分: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;
}

答案 9 :(得分:2)

下面是一些将字节数组转换为字符串的方法。我测试过它们效果很好。

public String getStringFromByteArray(byte[] settingsData) {

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(settingsData);
    Reader reader = new BufferedReader(new InputStreamReader(byteArrayInputStream));
    StringBuilder sb = new StringBuilder();
    int byteChar;

    try {
        while((byteChar = reader.read()) != -1) {
            sb.append((char) byteChar);
        }
    }
    catch(IOException e) {
        e.printStackTrace();
    }

    return sb.toString();

}

public String getStringFromByteArray(byte[] settingsData) {

    StringBuilder sb = new StringBuilder();
    for(byte willBeChar: settingsData) {
        sb.append((char) willBeChar);
    }

    return sb.toString();

}

答案 10 :(得分:2)

javax.xml.bind.DatatypeConverter应该这样做:

byte [] b = javax.xml.bind.DatatypeConverter.parseHexBinary("E62DB");
String s = javax.xml.bind.DatatypeConverter.printHexBinary(b);

答案 11 :(得分:1)

尽管

new String(bytes, "UTF-8")

是正确的,它抛出一个UnsupportedEncodingException,它迫使您处理一个已检查的异常。从Java 1.6开始,您可以使用另一个构造函数作为替代,以将字节数组转换为String

new String(bytes, StandardCharsets.UTF_8)

这不会引发任何异常。

也应使用StandardCharsets.UTF_8进行转换:

"test".getBytes(StandardCharsets.UTF_8)

同样,您避免处理被检查的异常。

答案 12 :(得分:1)

我用这种方法成功地将字节数组转换为字符串:

public static String byteArrayToString(byte[] data){
    String response = Arrays.toString(data);

    String[] byteValues = response.substring(1, response.length() - 1).split(",");
    byte[] bytes = new byte[byteValues.length];

    for (int i=0, len=bytes.length; i<len; i++) {
        bytes[i] = Byte.parseByte(byteValues[i].trim());
    }

    String str = new String(bytes);
    return str.toLowerCase();
}

答案 13 :(得分:1)

虽然base64编码是安全的,并且可以争辩“正确的答案”,但我到这里寻找一种方法将Java字节数组转换为Java String或从Java String转换。也就是说,字节数组的每个成员在其String对应项中保持不变,编码/传输不需要额外的空间。

描述8位透明编码的

This answer对我非常有帮助。我在TB级二进制数据上使用ISO-8859-1来回成功转换(二进制&lt; - &gt; String),而没有base64编码所需的膨胀空间要求,因此对我的用例YMMV是安全的。< / p>

This was also helpful解释何时/是否应该进行实验。

答案 14 :(得分:0)

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);
}

答案 15 :(得分:0)

这个对我来说最多适用于Android Q:

您可以使用以下方法将十六进制字符串转换为字符串

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        var x = 0
        var y = 0
        while(x<10){
           while(y<10){
                
                let button = UIButton(frame: CGRect(x: (x+1)*50, y: (y+1)*50, width: 50, height: 50))
                button.backgroundColor = .green
                button.setTitle("(" + String(x) + ", " + String(y) + ")", for: .normal)
                button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)

                self.view.addSubview(button)
                y+=1
            }
            x+=1
        }
    }

    @objc func buttonAction(sender: UIButton!) {
        print("Button " + sender.title(for: .normal)! + " tapped")
    }
}

使用以下命令将字节数组转换为十六进制字符串

    public static String hexToString(String hex) {
    StringBuilder sb = new StringBuilder();
    char[] hexData = hex.toCharArray();
    for (int count = 0; count < hexData.length - 1; count += 2) {
        int firstDigit = Character.digit(hexData[count], 16);
        int lastDigit = Character.digit(hexData[count + 1], 16);
        int decimal = firstDigit * 16 + lastDigit;
        sb.append((char)decimal);
    }
    return sb.toString();
}

答案 16 :(得分:-1)

您可以使用简单的for循环进行转换:

public void byteArrToString(){
   byte[] b = {'a','b','$'};
   String str = ""; 
   for(int i=0; i<b.length; i++){
       char c = (char) b[i];
       str+=c;
   }
   System.out.println(str);
}

答案 17 :(得分:-1)

尝试在两次转换中指定8位字符集。例如ISO-8859-1。

答案 18 :(得分:-1)

这是工作代码。

            // Encode byte array into string . TemplateBuffer1 is my bytearry variable.

        String finger_buffer = Base64.encodeToString(templateBuffer1, Base64.DEFAULT);
        Log.d(TAG, "Captured biometric device->" + finger_buffer);


        // Decode String into Byte Array. decodedString is my bytearray[] 
        decodedString = Base64.decode(finger_buffer, Base64.DEFAULT);

答案 19 :(得分:-1)

使用StringByteArrayInputStream读取字节,并用BufferedReader包装,这是Char Stream而不是Byte Stream,它将字节数据转换为String。

package com.cs.sajal;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class TestCls {

    public static void main(String[] args) {

        String s=new String("Sajal is  a good boy");

        try
        {
        ByteArrayInputStream bis;
        bis=new ByteArrayInputStream(s.getBytes("UTF-8"));

        BufferedReader br=new BufferedReader(new InputStreamReader(bis));
        System.out.println(br.readLine());

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }
}

输出是:

  

Sajal是一个好孩子

答案 20 :(得分:-2)

InputStream is = new FileInputStream("/home/kalt/Desktop/SUDIS/READY/ds.bin");
byte[] bytes = IOUtils.toByteArray(is);

答案 21 :(得分:-3)

public class byteString {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        String msg = "Hello";
        byte[] buff = new byte[1024];
        buff = msg.getBytes("UTF-8");
        System.out.println(buff);
        String m = new String(buff);
        System.out.println(m);


    }

}

答案 22 :(得分:-3)

字符串是char的集合(16位无符号)。因此,如果您要将负数转换为字符串,它们将在翻译中丢失。

答案 23 :(得分:-5)

使用Base64并解决您的问题。它太易于使用了。 http://iharder.sourceforge.net/current/java/base64/