How to convert byte array to string and vice versa?
Как преобразовать массив байтов в строку и наоборот?
Мне нужно преобразовать массив байтов в строку в Android, но мой массив байтов содержит отрицательные значения.
Если я снова преобразовываю эту строку в массив байтов, значения, которые я получаю, отличаются от исходных значений массива байтов.
Что я могу сделать, чтобы получить правильное преобразование? Код, который я использую для преобразования, следующий:
// Code to convert byte arr to str: byte[] by_original = {0,1,-2,3,-4,-5,6}; Stringstr1=newString(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 = {...} Stringstr=newString(bytes, StandardCharsets.UTF_8); // for UTF-8 encoding
Существует множество кодировок, которые вы можете использовать, посмотрите поддерживаемые кодировки в Oracle javadocs.
Ответ 2
"Правильное преобразование" между byte[] и String заключается в явном указании кодировки, которую вы хотите использовать. Если вы начинаете с byte[] и на самом деле он не содержит текстовых данных, нет "правильного преобразования". Strings предназначены для текста, byte[] - для двоичных данных, и единственное, что действительно разумно делать, это избегать преобразования между ними, если только это не является абсолютно необходимым.
Если вам действительно необходимо использовать String для хранения двоичных данных, то самый безопасный способ - использовать кодировку Base64.
Ответ 3
Основная проблема заключается (я думаю) в том, что вы невольно используете набор символов, для которого:
bytes != encode(decode(bytes))
в некоторых случаях. Примером такого набора символов является UTF-8. В частности, определенные последовательности байтов не являются допустимыми кодировками в UTF-8. Если декодер UTF-8 обнаружит одну из этих последовательностей, он может отбросить байты-нарушители или декодировать их как кодовую точку Unicode для обозначения "такого символа нет". Естественно, когда вы затем попытаетесь закодировать символы в виде байтов, результат будет другим.
Решение таково:
Четко указывайте кодировку символов, которую вы используете; т. е. Используйте строковый конструктор и String.toByteArray метод с явной кодировкой.
Используйте правильный набор символов для ваших байтовых данных ... или альтернативно один (например, "Latin-1", где все последовательности байтов соответствуют допустимым символам Юникода.
Если ваши байты (на самом деле) представляют собой двоичные данные и вы хотите иметь возможность передавать / принимать их по "текстовому" каналу, используйте что-то вроде кодировки Base64 ... который предназначен для этой цели.
Для Java наиболее распространенными наборами символов являются в java.nio.charset.StandardCharsets. Если вы кодируете строку, которая может содержать любое значение символа Юникода, то рекомендуется использовать кодировку UTF-8 (UTF_8).
Если вам нужно отображение 1: 1 в Java, то вы можете использовать латинский алфавит ISO № 1 - чаще называемый просто "Latin 1" или просто "Latin" (ISO_8859_1). Обратите внимание, что Latin-1 в Java - это версия Latin-1 для IANA, которая присваивает символы всем возможным 256 значениям, включая управляющие блоки C0 и C1. Они недоступны для печати: вы не увидите их ни в одном выводе.
Начиная с Java 8, Java содержит java.util.Base64 для кодирования / декодирования Base64. Для кодирования, безопасного для URL, вы можете захотеть использовать Base64.getUrlEncoder вместо стандартного кодировщика. Этот класс также присутствует в Android начиная с Android Oreo (8), уровень API 26.
Байты результирующей строки различаются в зависимости от того, какую кодировку вы используете. новая строка (bytes) и new String(bytes, Charset.forName("utf-8")) и новая строка(bytes, Charset.forName("utf-16")) будут иметь разные массивы байтов при вызове String#getBytes() (в зависимости от кодировки по умолчанию)