Как преобразовать двоичные данные в строки и обратно в Java?
-
09-06-2019 - |
Вопрос
У меня есть двоичные данные в файле, которые я могу без проблем считать в массив байтов и обработать.Теперь мне нужно отправить части данных по сетевому соединению как элементы XML-документа.Моя проблема в том, что когда я конвертирую данные из массива байтов в строку и обратно в массив байтов, данные повреждаются.Я протестировал это на одной машине, чтобы изолировать проблему преобразования строк, поэтому теперь я знаю, что она не повреждается синтаксическим анализатором XML или сетевым транспортом.
То, что у меня есть сейчас, это
byte[] buffer = ...; // read from file
// a few lines that prove I can process the data successfully
String element = new String(buffer);
byte[] newBuffer = element.getBytes();
// a few lines that try to process newBuffer and fail because it is not the same data anymore
Кто-нибудь знает, как преобразовать двоичный файл в строку и обратно без потери данных?
Ответил:Спасибо, Сэм.Я чувствую себя идиотом.Вчера я получил ответ на этот вопрос, потому что мой парсер SAX жаловался.По какой-то причине, когда я столкнулся с этой, казалось бы, отдельной проблемой, мне не пришло в голову, что это новый симптом той же проблемы.
РЕДАКТИРОВАТЬ:Просто для полноты картины я использовал База64 класс из Апач Коммонс Кодек пакет для решения этой проблемы.
Решение
Если вы закодируете его в base64, это превратит любые данные в безопасный текст ascii, но данные в кодировке base64 больше, чем исходные данные.
Другие советы
Строка(байт[]) обрабатывает данные как кодировку символов по умолчанию.Таким образом, способ преобразования байтов из 8-битных значений в 16-битные символы Java Unicode будет различаться не только в разных операционных системах, но даже может различаться у разных пользователей, использующих разные кодовые страницы на одном и том же компьютере!Этот конструктор годится только для декодирования одного из ваших собственных текстовых файлов.Не пытайтесь преобразовать произвольные байты в символы в Java!
Кодирование как база64 это хорошее решение.Вот как файлы передаются по SMTP (электронная почта).(Бесплатный) Апач Кодек Commons проект выполнит свою работу.
byte[] bytes = loadFile(file);
//all chars in encoded are guaranteed to be 7-bit ASCII
byte[] encoded = Base64.encodeBase64(bytes);
String printMe = new String(encoded, "US-ASCII");
System.out.println(printMe);
byte[] decoded = Base64.decodeBase64(encoded);
Альтернативно вы можете использовать Java 6. Конвертер типов данных:
import java.io.*;
import java.nio.channels.*;
import javax.xml.bind.DatatypeConverter;
public class EncodeDecode {
public static void main(String[] args) throws Exception {
File file = new File("/bin/ls");
byte[] bytes = loadFile(file, new ByteArrayOutputStream()).toByteArray();
String encoded = DatatypeConverter.printBase64Binary(bytes);
System.out.println(encoded);
byte[] decoded = DatatypeConverter.parseBase64Binary(encoded);
// check
for (int i = 0; i < bytes.length; i++) {
assert bytes[i] == decoded[i];
}
}
private static <T extends OutputStream> T loadFile(File file, T out)
throws IOException {
FileChannel in = new FileInputStream(file).getChannel();
try {
assert in.size() == in.transferTo(0, in.size(), Channels.newChannel(out));
return out;
} finally {
in.close();
}
}
}
Посмотрите этот вопрос, Как встроить двоичные данные в XML?Вместо преобразования byte[] в String с последующей передачей куда-либо в XML, преобразуйте byte[] в String с помощью кодировки BASE64 (в некоторых библиотеках XML есть тип, позволяющий сделать это за вас).Декодирование BASE64 происходит после получения строки из XML.
Использовать http://commons.apache.org/codec/
Ваши данные могут быть перепутаны из-за всевозможных странных ограничений набора символов и присутствия непечатаемых символов.Палка с BASE64.
Как вы создаете свой XML-документ?Если вы используете встроенные в Java классы XML, то кодирование строк должно обрабатываться за вас.
Взгляните на пакеты javax.xml и org.xml.Это то, что мы используем для создания XML-документов, и он довольно хорошо справляется со всем кодированием и декодированием строк.
---РЕДАКТИРОВАТЬ:
Хм, кажется, я неправильно понял проблему.Вы пытаетесь закодировать не обычную строку, а некоторый набор произвольных двоичных данных?В этом случае, вероятно, подойдет кодировка Base64, предложенная в предыдущем комментарии.Я считаю, что это довольно стандартный способ кодирования двоичных данных в XML.