Как преобразовать двоичные данные в строки и обратно в Java?

У меня есть двоичные данные в файле, которые я могу прочитать в байтовый массив и обработать без проблем. Теперь мне нужно отправить части данных по сетевому соединению в виде элементов XML-документа. Моя проблема в том, что когда я конвертирую данные из массива байтов в String и обратно в массив байтов, данные повреждаются. Я протестировал это на одной машине, чтобы изолировать проблему от преобразования String, поэтому теперь я знаю, что он не повреждается синтаксическим анализатором 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

Кто-нибудь знает, как преобразовать двоичный файл в String и обратно без потери данных?

Ответил: Спасибо, Сэм. Я чувствую себя идиотом. Я получил ответ вчера, потому что мой парсер SAX жаловался. По какой-то причине, когда я столкнулся с этой, казалось бы, отдельной проблемой, мне не пришло в голову, что это новый симптом той же проблемы.

Обновлено: Для полноты картины я использовал класс Base64 из пакета Apache CommonsКодек для решения этой проблемы.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
29
0
98 166
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Если вы закодируете его в base64, это превратит любые данные в безопасный текст ascii, но данные в кодировке base64 больше, чем исходные данные

Как вы строите свой XML-документ? Если вы используете встроенные в Java классы XML, то кодирование строк должно выполняться за вас.

Взгляните на пакеты javax.xml и org.xml. Это то, что мы используем для создания XML-документов, и он довольно хорошо обрабатывает все кодирование и декодирование строк.

---Обновлено:

Хм, кажется, я неправильно понял проблему. Вы пытаетесь кодировать не обычную строку, а некоторый набор произвольных двоичных данных? В этом случае, вероятно, лучше использовать кодировку Base64, предложенную в предыдущем комментарии. Я считаю, что это довольно стандартный способ кодирования двоичных данных в XML.

См. Этот вопрос, Как встраивать двоичные данные в XML? Вместо того, чтобы преобразовывать byte [] в String, а затем куда-нибудь помещать их в XML, преобразуйте byte [] в String с помощью кодировки BASE64 (в некоторых библиотеках XML есть тип, который сделает это за вас). Декодирование BASE64 после получения строки из XML.

Используйте http://commons.apache.org/codec/

Ваши данные могут быть испорчены из-за всевозможных странных ограничений набора символов и наличия не связанных символов. Палка с BASE64.

Строка (байт []) обрабатывает данные как кодировку символов по умолчанию. Итак, то, как байты преобразуются из 8-битных значений в 16-битные символы Java Unicode, будет различаться не только в разных операционных системах, но даже у разных пользователей, использующих разные кодовые страницы на одной машине! Этот конструктор подходит только для декодирования одного из ваших собственных текстовых файлов. Не пытайтесь преобразовать произвольные байты в символы в Java!

Кодирование как base64 - хорошее решение. Таким образом файлы отправляются через SMTP (электронная почта). (Бесплатный) проект Apache Кодек 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 DatatypeConverter:

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

Другие вопросы по теме