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

Java 如何将字节数组转换为字符串,反之亦然?,java,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 >>

我必须在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);
//将字节arr转换为str的代码:
字节[]由_original={0,1,-2,3,-4,-5,6};
String str1=新字符串(由_原件);
System.out.println(“str1>>”+str1);
//将str转换为字节arr的代码:
byte[]by_new=str1.getBytes();

对于(int i=0;i字符串是字符的集合(16位无符号)。因此,如果要将负数转换为字符串,它们将在转换过程中丢失。

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

您的字节数组必须有一些编码。如果有负值,则编码不能是ASCII。一旦您弄清楚了这一点,就可以将一组字节转换为字符串字符串使用:

byte[] bytes = {...}
String str = new String(bytes, StandardCharsets.UTF_8); // for UTF-8 encoding
您可以使用一系列编码,请查看中支持的编码。

使用
新字符串(按原文)
并使用
getBytes()
转换回
字节[]
不能保证两个
字节[]
的值相等。这是由于调用
StringCoding.encode(…)
字符串
编码为
Charset.defaultCharset()
。在编码过程中,编码器可能会选择替换未知字符并进行其他更改。因此,使用
String.getBytes()
可能不会返回与您最初传递给构造函数相同的数组。

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

 bytes != encode(decode(bytes))
在某些情况下,UTF-8就是此类字符集的一个示例。具体而言,某些字节序列在UTF-8中是无效的编码。如果UTF-8解码器遇到这些序列中的一个,则可能会丢弃有问题的字节,或将其解码为“无此类字符”的Unicode码点。当然,当您尝试将字符编码为字节时,结果会有所不同

解决办法是:

  • 明确说明您正在使用的字符编码;即使用字符串构造函数和带有显式字符集的
    String.toByteArray
    方法
  • 为字节数据使用正确的字符集…或者选择一个字符集(如“Latin-1”),其中所有字节序列都映射到有效的Unicode字符
  • 如果您的字节(实际上)是二进制数据,并且您希望能够通过“基于文本”的通道传输/接收它们,请使用类似Base64编码的方法……这是为此目的而设计的
  • byte[]
    String
    之间的“正确转换”是为了明确说明要使用的编码。如果以
    byte[]
    开头,而实际上它不包含文本数据,则不存在“正确转换”。
    String
    s表示文本,
    byte[]
    适用于二进制数据,唯一真正明智的做法是避免在它们之间进行转换,除非您必须这样做


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

    我们只需要用数组构造一个新的
    字符串


    结果字符串的字节因使用的字符集而异。调用string#getBytes()时,新字符串(字节)和新字符串(字节,charset.forName(“utf-8”))以及新字符串(字节,charset.forName(“utf-16”))都将具有不同的字节数组(取决于默认字符集)为什么会出现问题:有人已经指定: 如果以字节[]开头,而实际上它不包含文本数据,那么就没有“适当的转换”。字符串用于文本,字节[]用于二进制数据,唯一真正明智的做法是避免在它们之间进行转换,除非您必须这样做

    当我试图从pdf文件创建byte[]并将其转换为字符串,然后将字符串作为输入并转换回文件时,我发现了这个问题。

    因此,请确保您的编码和解码逻辑与我的相同。我将字节[]显式编码为Base64,并对其进行解码以再次创建文件

    用例: 由于某些限制,我试图在
    请求(POST)
    中发送
    字节[]
    ,过程如下:

    // 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);
    
    PDF文件>>Base64.encodeBase64(字节[])>>字符串>>发送请求(POST)>>接收字符串>>Base64.decodeBase64(字节[])>>创建二进制文件

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

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

    这对我来说很好:

    String cd="Holding some value";
    
    从字符串转换为字节[]:

    byte[] cookie = new sun.misc.BASE64Decoder().decodeBuffer(cd);
    
    从字节[]转换为字符串:

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

    javax.xml.bind.DatatypeConverter
    应该执行以下操作:

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

    我使用以下方法成功地将字节数组转换为字符串:

    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();
    }
    
    公共静态字符串byteArrayToString(字节[]数据){
    字符串响应=Arrays.toString(数据);
    String[]byteValues=response.substring(1,response.length()-1);
    byte[]bytes=新字节[byteValues.length];
    
    对于(int i=0,len=bytes.length;i使用
    ByteArrayInputStream
    String
    读取字节,并用
    BufferedReader
    将其包装,后者是字符流,而不是将字节数据转换为字符串的字节流

    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();
            }
    
        }
    }
    
    输出为:

    萨哈尔是个好孩子


    我确实注意到了一些答案中没有的东西。你可以将字节数组中的每个字节转换为字符,然后将它们放入一个字符数组。然后字符串就是cbuf是字符数组的地方。要转换回去,通过将每个字符转换为字节的字符串循环,放入一个字节数组,这个字节数组将与e首先

    new String(cbuf)
    
    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);
        }
    
    }
    
    
    
    公共类StringByTearTest{
    公共静态void main(字符串[]args){
    //把他想要的字节数组放进去
    
    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();
            }
    
        }
    }
    
    new String(cbuf)
    
    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);
        }
    
    }
    
    
    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();
    
    }
    
                // 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);
    
    InputStream is = new FileInputStream("/home/kalt/Desktop/SUDIS/READY/ds.bin");
    byte[] bytes = IOUtils.toByteArray(is);
    
    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);
    }
    
    new String(bytes, "UTF-8")
    
    new String(bytes, StandardCharsets.UTF_8)
    
    "test".getBytes(StandardCharsets.UTF_8)
    
        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();
    }
    
        public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }