Java String преобразование в шестнадцатеричное - PullRequest
1 голос
/ 21 января 2010

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

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

 {
 ...
}

где 'connection' - объект сокета.

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

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

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

Ответы [ 4 ]

5 голосов
/ 21 января 2010

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

2 голосов
/ 21 января 2010

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

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

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

1 голос
/ 21 января 2010

При преобразовании байтов в символы с 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 голосов
/ 21 января 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...