Как преобразовать байтовый массив в строку и наоборот? - PullRequest
211 голосов
/ 08 октября 2009

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

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

Ответы [ 23 ]

325 голосов
/ 08 октября 2009

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

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

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

98 голосов
/ 08 октября 2009

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

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

36 голосов
/ 08 октября 2009

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

 bytes != encode(decode(bytes))

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

Решение:

  1. Будьте откровенны в отношении кодировки символов, которую вы используете; то есть использовать конструктор String и метод String.toByteArray с явным набором символов.
  2. Используйте правильный набор символов для ваших байтовых данных ... или альтернативно (например, "Latin-1", где все последовательности байтов отображаются в действительные символы Юникода.
  3. Если ваши байты (действительно) являются двоичными данными, и вы хотите иметь возможность передавать / получать их по «текстовому» каналу, используйте что-то вроде кодировки Base64 ... , которая предназначена для этой цели .
31 голосов
/ 11 февраля 2013

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

String s = new String(bytes);

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

12 голосов
/ 08 октября 2009

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

9 голосов
/ 10 июля 2013

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

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

Поэтому убедитесь, что ваша логика кодирования и декодирования такая же, как у меня. Я явно закодировал байт [] в Base64 и расшифровал его, чтобы снова создать файл.

Использование регистра: Из-за некоторых ограничений я пытался отправить byte[] в request(POST), и процесс был следующим:

Файл PDF >> Base64.encodeBase64 (byte []) >> String >> Отправить в запросе (POST) >> String >> 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();
        }
6 голосов
/ 09 апреля 2014

Это прекрасно работает для меня:

String cd="Holding some value";

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

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

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

cd = new sun.misc.BASE64Encoder().encode(cookie);
5 голосов
/ 15 января 2017

Я заметил что-то, чего нет ни в одном из ответов. Вы можете преобразовать каждый из байтов в массиве байтов в символы и поместить их в массив символов. Тогда строка будет

new String(cbuf)
, где 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);
    }

}

5 голосов
/ 28 января 2015
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;
}
2 голосов
/ 20 июля 2017

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

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...