Как надежно записать байтовый массив

Предположим, у меня есть массив байтов, который нужно преобразовать в массив символов и отправить по сети. например

char[] sometoken = String( myByteArray ).toCharArray();
myMethodToSendByteArrayUsingTCPSocket( sometoken );

myByteArray - это кодировка ASN.1 (является Kerberos TGT). На принимающей стороне я использую этот код для записи «sometoken» в файл.

   try{
        fileName = .....;
        fs =  new FileOutputStream(fileName)  ;
        fs.write( new String( sometoken ).getBytes() );         
        fs.flush();
        fs.close(); 
    }catch(IOException e){
        e.printStackTrace();
    }

Могу я спросить, должен ли я использовать DataOutputStream для записи в файл для надежности? Кроме того, я считаю, что необходимо указать кодировку ASN.1 для getBytes(). Это getBytes("ASN.1") ?

Спасибо.


person dorothy    schedule 17.07.2014    source источник
comment
Предположим, у меня есть массив байтов, который нужно преобразовать в массив символов - вот ваша первая ошибка. К тому времени, как вы преобразовали массив произвольных байтов в строку, вы безнадежно испортили данные.   -  person Hot Licks    schedule 17.07.2014
comment
@HotLicks, но мне нужно передать char[] в метод myMethodToSendByteArrayUsingTCPSocket(). Он принимает только аргументы типа char[]. Благодарность   -  person dorothy    schedule 17.07.2014
comment
Резервное копирование. Какие данные вы отправляете? Откуда это? На что это похоже? И кто на другом конце получает данные?   -  person Hot Licks    schedule 17.07.2014
comment
@HotLicks, я указал, что это билет Kerberos. нужно отправить этот билет на какой-то другой сервер, но сначала нужно преобразовать его в char[]. После этого я хочу вернуть билет с оригинальной кодировкой. Билет Kerberos создается с помощью getEncoded() из модуля KerberosTicket. getEncoded() генерирует билет в кодировке ASN.1. Благодарность   -  person dorothy    schedule 17.07.2014
comment
String( myByteArray ) должно быть new String( myByteArray, encoding ). ASN.1 не является кодировкой символов. Вы не можете написать getBytes("ASN.1"). Вы должны использовать библиотеку Java ASN.1. Кроме того, char[] содержит символы UTF-16BE. Это действительно то, что требует ваш проводной протокол?   -  person David Conrad    schedule 17.07.2014
comment
Я пропустил это: myByteArray - это кодировка ASN.1. Вам нужно использовать библиотеку ASN.1 для ее анализа, вы не можете просто преобразовать ее в строку.   -  person David Conrad    schedule 17.07.2014
comment
Из того, что я вижу, ASN.1 - это двоичные данные, и их нельзя преобразовать без потерь в/из символьных данных.   -  person Hot Licks    schedule 17.07.2014
comment
(Обратите внимание, что существует значительная разница в значении между char C и Java. На языке C массив char может быть символьными данными или может быть чисто двоичным - 8 бит на char в любом случае. В Java массив char - это массив 16-битных символов UTF16, точка.)   -  person Hot Licks    schedule 17.07.2014
comment
@HotLicks Массив char представляет собой произвольную последовательность кодовых единиц UTF-16. (String — это последовательность кодовых единиц UTF-16, которые содержат допустимые кодовые точки UTF-16.)   -  person Tom Blodget    schedule 18.07.2014
comment
Привет, моя основная цель - только сохранить этот билет и использовать его на других машинах. stackoverflow.com/questions/24817322/   -  person dorothy    schedule 18.07.2014
comment
@TomBlodget - На самом деле, я не верю, что есть какая-либо проверка того, что строка содержит только действительные кодовые точки UTF16. Но дело в том, что вам нужно приложить все усилия, чтобы использовать массив Java char для двоичного кода, тогда как в C это делается постоянно (и другого варианта действительно нет). Таким образом, при чтении документа интерфейса, написанного с точки зрения C, часто используется терминология, которая по существу не имеет смысла для Java.   -  person Hot Licks    schedule 18.07.2014


Ответы (2)


Это постоянно происходит в реальном мире. Каждый раз, когда вы просматриваете изображение в браузере, вы видите строку байтовых данных, отправленных через сокет. Просто BASE64 кодирует ваши данные, которые преобразуют байты в «печатный» текст ASCII. Затем передайте это и реверсируйте на дальнем конце.

person Greycon    schedule 17.07.2014
comment
Существуют способы передачи данных без кодирования Base64. И обе стороны должны согласиться, если будет использоваться схема Base64. - person Hot Licks; 17.07.2014
comment
ваше описание неверно (вы можете отправлять двоичные данные через сокет, не преобразовывая их в строковые данные, на самом деле это предпочтительнее), однако ваш ответ на этот вопрос правильный (используйте кодировку Base64). - person jtahlborn; 17.07.2014

Вы можете использовать набор символов "CP437" для передачи данных туда и обратно без потери данных. Он имеет 256 символов, по одному байту на символ. Как отмечают другие, обе стороны должны согласиться.

С другой стороны, byteArray действительно должен быть отправлен. А так как вы сначала сохраняете в файл, просто используйте java.nio.files.Files.write(Path path, byte[] bytes, OpenOption.. . параметры).

person Tom Blodget    schedule 18.07.2014