Как преобразовать байтовый массив в строку и наоборот?

Мне нужно преобразовать массив байтов в строку в 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);

Я застрял в этой проблеме.

Ответ 1

Ваш массив байтов должен иметь некоторую кодировку. Кодировка не может быть ASCII, если у вас есть отрицательные значения. Как только вы это выясните, вы можете преобразовать набор байтов в строку, используя:

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

Существует множество кодировок, которые вы можете использовать, посмотрите класс Charset в Sun javadocs.

Ответ 2

"Правильное преобразование" между byte[] и String - это явно указать кодировку, которую вы хотите использовать. Если вы начинаете с byte[] и на самом деле не содержат текстовых данных, нет "правильного преобразования". String предназначены для текста, byte[] для двоичных данных, и единственно разумная вещь, которую нужно сделать, - избегать конвертации между ними, если только вам это не нужно.

Если вы действительно должны использовать String для хранения двоичных данных, самым безопасным способом будет использование Base64.

Ответ 3

Проблема с корнем (я думаю), что вы невольно используете набор символов, для которого:

 bytes != encode(decode(bytes))

в некоторых случаях. UTF-8 является примером такого набора символов. В частности, некоторые последовательности байтов не являются допустимыми кодировками в UTF-8. Если декодер UTF-8 встречает одну из этих последовательностей, он может отбросить оскорбительные байты или декодировать их как кодовый номер Юникода для "нет такого символа". Естественно, когда вы затем пытаетесь кодировать символы как байты, результат будет другим.

Решение:

  • Будьте откровенны в кодировке символов, которую вы используете; т.е. использовать конструктор String и метод String.toByteArray с явной кодировкой.
  • Используйте правильный набор символов для ваших байтовых данных... или, альтернативно, один (например, "Latin-1", где все байтовые последовательности соответствуют действующим символам Unicode.
  • Если ваши байты являются (действительно) двоичными данными и вы хотите иметь возможность передавать/получать их по каналу, основанному на тексте, используйте что-то вроде кодировки Base64..., которая предназначена для этой цели.

Ответ 4

Нам просто нужно построить новый массив String с массивом: http://www.mkyong.com/java/how-do-convert-byte-array-to-string-in-java/

String s = new String(bytes);

Байты результирующей строки различаются в зависимости от того, какую кодировку вы используете. новая строка (байты) и новая строка (байты, Charset.forName( "utf-8" )) и новая строка (bytes, Charset.forName( "utf-16" )) будут иметь разные байтовые массивы при вызове String # getBytes() (в зависимости от кодировки по умолчанию)

Ответ 5

Использование new String(byOriginal) и преобразование обратно в byte[] с помощью getBytes() не гарантирует двух byte[] с равными значениями. Это вызвано вызовом StringCoding.encode(..), который будет кодировать String до Charset.defaultCharset(). Во время этой кодировки кодер может выбрать замену неизвестных символов и другие изменения. Следовательно, использование String.getBytes() может не вернуть равный массив, как вы первоначально передали конструктору.

Ответ 6

Почему возникла проблема: Как уже указывалось:  Если вы начинаете с байта [], и на самом деле он не содержит текстовых данных, нет "правильного преобразования". Строки для текста, byte [] - для двоичных данных, и единственно разумная вещь - избегать конвертации между ними, если вам не нужно.

Я наблюдал эту проблему, когда пытался создать байт [] из файла pdf, а затем преобразовал его в String, а затем взял String как вход и преобразовал обратно в файл.

Поэтому убедитесь, что ваша логика кодирования и декодирования такая же, как и я. Я явно закодировал байт [] на 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();
        }

Ответ 7

Это отлично работает для меня:

String cd="Holding some value";

Преобразование из строки в байт []:

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

Преобразование из байта [] в строку:

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

Ответ 8

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

Я заметил что-то, чего нет в ответах. Вы можете отнести каждый из байтов в массиве байтов к символам и поместить их в массив 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);
    }

}

Ответ 10

javax.xml.bind.DatatypeConverter должен сделать это:

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

Ответ 11

Вот несколько методов, которые преобразуют массив байтов в строку. Я тестировал их, они хорошо работают.

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

}

Ответ 12

Мне удалось преобразовать байтовый массив в строку с помощью этого метода:

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

В то время как кодировка base64 безопасна, и можно утверждать "правильный ответ", я пришел сюда, чтобы найти способ преобразования массива байтов Java в/из Java String as-is. То есть, когда каждый член байтового массива остается неповрежденным в своем экземпляре String, без дополнительного пространства, необходимого для кодирования/транспорта.

Этот ответ, описывающий 8-битные прозрачные кодировки, очень помог мне. Я использовал ISO-8859-1 на терабайтах двоичных данных, чтобы конвертировать назад и вперед успешно (двоичный ↔ String) без требований к раздутому пространству, необходимых для кодирования base64, так что это безопасно для моего использования - YMMV.

Это было также полезно в объяснении, когда/если вы должны экспериментировать.

Ответ 14

Даже если

new String(bytes, "UTF-8")

правильно, он UnsupportedEncodingException исключение UnsupportedEncodingException которое заставляет вас иметь дело с проверенным исключением. Вы можете использовать в качестве альтернативы другой конструктор, начиная с Java 1.6, для преобразования байтового массива в String:

new String(bytes, StandardCharsets.UTF_8)

Этот не бросает никаких исключений.

Обратное преобразование также должно быть сделано с помощью StandardCharsets.UTF_8:

"test".getBytes(StandardCharsets.UTF_8)

Опять же, вам не нужно иметь дело с проверенными исключениями.

Ответ 15

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

Ответ 16

Попробуйте указать 8-битную кодировку в обоих преобразованиях. ISO-8859-1, например.

Ответ 17

Прочитайте байты из String с помощью ByteArrayInputStream и оберните его BufferedReader, который представляет собой Char поток вместо потока байтов, который преобразует данные байта в строку.

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

    }
}

Выход:

Саял - хороший мальчик

Ответ 18

Здесь рабочий код.

            // 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

Вы можете использовать простой цикл 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);
}

Ответ 20

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

Ответ 21

Строка представляет собой набор из char (16 бит без знака). Поэтому, если вы собираетесь конвертировать отрицательные числа в строку, они будут потеряны в переводе.

Ответ 22

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


    }

}