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

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

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

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

РЕДАКТИРОВАТЬ: просто ради полноты, я использовал класс Base64 из пакета кодека Apache Commons для решения этой проблемы.

21.08.2008 18:51:52
4 ОТВЕТА
РЕШЕНИЕ

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

19
21.08.2008 18:54:06

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

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

---РЕДАКТИРОВАТЬ:

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

0
21.08.2008 19:10:31

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

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

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

2
23.05.2017 12:32:20

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

Кодирование как base64 - хорошее решение. Вот как файлы отправляются через SMTP (электронная почта). (Бесплатный) проект Apache Commons Codec сделает эту работу.

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();
    }
  }
}
35
26.11.2013 04:45:39