2010-01-21 3 views
1

Я работаю над прослушивателем сокета tcp/ip, который прослушивает порт 80 для данных, поступающих с удаленных хостов. Теперь эти входящие данные находятся в нечитаемом формате, поэтому я сохранил эти входящие данные, поскольку они находятся в строке, а затем преобразовал эту строку в массив символов, а затем для каждого индекса в массиве, я преобразовал содержимое в шестнадцатеричный. Теперь проблема в том, что данные преобразуются в шестнадцатеричные, но в некоторых местах преобразование не является правильным, а итоговая гексагональная часть - «fffd». находится в том месте, где полученный hex должен быть «bc» (0xBC), это «fffd» (0xFF 0xFD). Я вынужден полагать, что некоторые части входящих данных не читаются должным образом с помощью моей java-программы. Я использую BufferefInputStream и InputStreamReader для чтения входящих данных и проверяю конец потока следующим образом.Преобразование строки Java в hex

BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); 
    InputStreamReader isr = new InputStreamReader(is); 
    while(isr.read()!=-1) 

{ 
... 
} 

где «соединение» - это объект сокета.

Входные данные, которые им получают через сокет: # SR, IN-0002005,10: 49: 37,16/01/2010, $ < 49X ™ с š @ (bN> ™ м šBB ©: 4ä ýÕ 01300> ÀäCåKöA ÷ Ð>.

шестнадцатиричное преобразование, что моя программа делает имеет „FFFD“ во многих местах, где другие значения шестнадцатеричных должны быть. конверсия, хотя правильно около 60% от входной строки

Любые указатели на то, почему мое преобразование в шестнадцатеричном преобразовании не то, что должно было бы, было бы очень полезно.

+0

звучит как проблема с кодировкой. вы принимаете во внимание формат, в котором поступают входящие данные в кодировке? – Aadith

+0

Я уверен, что это не проблема кодирования, поскольку мне говорят, что то же самое, что и в VB, дает другой и правильный результат. – ping

ответ

5

Я не думаю, что вы должны использовать читателя. чтение символов, вы, кажется, работаете с двоичными данными. Используйте InputStream напрямую и преобразуйте байты по мере их получения. символы java - это символы Unicode, которые, как я предполагаю, являются источником ваших проблем.

+0

Если это не проблема, не могли бы вы помочь мне с небольшим фрагментом, демонстрирующим дело? – ping

+0

@ping Из кода в вашем вопросе просто удалите строку, в которой вы создаете InputStreamReader, и замените все ссылки на этот Reader ссылками на InputStream, например. 'while (isr.read()! = - 1)' становится 'while (is.read()! = - 1)'. Хотя вам, вероятно, потребуется сохранить возвращаемое значение для чтения где-то, потому что это считанный байт, например. 'while ((nextByte = is.read())! = - 1)' –

2

Строки Java не так просто «злоупотреблять» для обработки прозрачных двоичных данных, как в VB (или большинстве других языков). VB обрабатывает строки внутренне как массив байтов, тогда как в Java строки являются упорядоченным списком символов.

В вашем случае вы вставляете свой InputStream в InputStreamReader, заставляя кодировку символов по умолчанию вашей платформы использоваться при преобразовании байтов, переданных из InputStream, в символы, доставленные InputStreamReader. Некоторые из используемых в основном наборов символов ISO 8859-X не используют байты в диапазонах от 0x00 до 0x1f и от 0x7f до 0xbf, поэтому, если вы используете такую ​​кодировку и читаете байт из этих диапазонов, InputStreamReader вернет «заменяющий символ» "с кодовой точкой 0xfffd, чтобы указать неизвестный символ.

Единственным «правильным» способом является отказ от InputStreamReader и использование массивов байтов для двоичных данных.

1

При преобразовании байтов символов с InputStreamReader, кодирование имеет огромное значение:

public static void main(String[] args) throws Exception { 
    checkEncoding("ISO-8859-1"); 
    checkEncoding("ISO-8859-9"); 
    checkEncoding("Windows-1252"); 
    checkEncoding("UTF-8"); 
    checkEncoding("UTF-16BE"); 
    checkEncoding("Big5"); 
    checkEncoding("Shift-JIS"); 
    } 

    private static void checkEncoding(String encoding) throws IOException { 
    byte[] all = new byte[256]; 
    for (int i = 0; i < all.length; ++i) all[i] = (byte) i; 
    ByteArrayInputStream bais = new ByteArrayInputStream(all); 
    InputStreamReader isr = new InputStreamReader(bais, encoding); 
    char[] ca = new char[256]; 
    int read = isr.read(ca); 
    System.out.println(encoding + ":" + read); 
    for (int i = 0; i < read; ++i) { 
     if (ca[i] != i) { 
     System.out.println(Integer.toHexString(i) + "->" + 
      Integer.toHexString(ca[i])); 
     } 
    } 
    } 

только один, который работает «как и ожидалось» является ISO-8859-1, которая определяется как первый 256 символов в Unicode. ISO-8859-9 и Windows-1252 также создают символы 1-для-1; 8859-9 имеет несколько разных символов, но 1252 имеет несколько 0xFFFD.

Из-за того, как расположены байты, все после 0x7F для UTF-8 не подходит. Конечно, вы получаете половину символов для UTF-16, а другие многобайтовые кодировки - беспорядок.

0

Для целей разработки рассмотрите тот, который уже включен в Eclipse для использования с этими веб-контейнерами с серверными коннекторами.

Смежные вопросы