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




Если вы закодируете его в 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();
}
}
}