Intereting Posts
Android View onSaveInstanceState не вызывается Как установить тип mime для прикрепления электронной почты Android Почему камера не запускается при запуске моего приложения Android с обновленной версией? Я пишу файл в Environment.DIRECTORY_DOWNLOADS, почему я не вижу его через приложение «Загрузки»? Android Unit Test: ActivityMonitor waitForActivityWithTimeout возвращает NULL, getActivity никогда не возвращается, ошибка разрешения INJECT_EVENTS Какое предварительное знание предполагает развитие Android? Не удалось выполнить метод активности Android SetText в фрагменте из другого действия, не связанного с фрагментом Значение Google Play «Устанавливается» Сохранение edittext в растровое изображение Android Databinding с меню У метода FingerprintManagerCompat были проблемы с устройствами Samsung Как выполнить тестирование класса, использующего HttpClient в Android, используя встроенную структуру? Применение тени с увеличением android Получить положение изображения на макете android

Динамический SAX-анализатор для кодированного XML-кода UTF-8 или ISO-8859-1

Я разрабатываю приложение для Android, где мне приходится разбирать различные XML-файлы. Большинство из них кодируются в UTF-8, но некоторые из них могут быть закодированы в ISO-8859-1.

HttpURLConnection con = (HttpURLConnection) url.openConnection(); ... in = con.getInputStream(); InputSource is = new InputSource(in); ... parser.parse(is, handler); 

Мой код для обработки ввода выглядит, как указано выше. В документации по java говорится о InputSource :

Если нет потока символов, но есть поток байтов, синтаксический анализатор будет использовать этот поток байтов, используя кодировку, указанную в InputSource, или иначе (если не указывается кодировка) автоопределение кодировки символов с использованием алгоритма, такого как Спецификации XML.

Я передаю ByteStream и я не указываю кодировку, поэтому в соответствии с документацией кодирование должно быть автоматически обнаружено. Но это не так. Все файлы, закодированные в UTF-8, прекрасны, но ISO-8859-1 не являются (я получаю Parser Expat... Exception for some invalid characters ). Если я устанавливаю кодировку InputSource вручную на «ISO-8859-1», он ведет себя наоборот.

Как я могу это решить? Я искал Google и Stackoverflow течение нескольких часов, но не нашел решение. Я также попытался передать CharacterStream в InputSource , но некоторые символы (äöüÄÖÜß) в файлах ISO-8859-1 все еще отображаются как «?» В моем приложении.

Заранее спасибо!

Лучшее решение зависит от точной причины вашей проблемы. Если вы извлекаете XML-документ через HTTP, кодировка также может быть указана в заголовке ответа Content-Type и не обязательно в самом документе XML. Если это так, и XML-библиотеки в Android правильно реализованы (я не могу проверить здесь, если заголовок Content + Type оценивается), вы должны иметь возможность создавать InputSource с URL-адресом, непосредственно new InputSource("http://..."); вместо.

Если кодировка не задана в заголовке HTTP и не указана в прологе XML, парсер корректно работает, если он предполагает кодировку UTF-8 (как указано в спецификации XML). Автоопределение, упомянутое в документации, не означает, что анализатор фактически просматривает содержимое документа, чтобы сделать предположение о кодировке, но означает, что он проверяет атрибут кодирования потока XML. Если атрибут кодирования отсутствует, по умолчанию используется UTF-8.

Я бы предложил проверить, есть ли символы, которые не находятся в старом наборе ascii, и перекодировать строку, если есть символы UTF-8:

 String output=new String(input.getBytes("8859_1"), "utf-8"); 

Эта строка принимает ISO-8859-1 и преобразует ее в utf-8, который используется Java.

Самый простой способ – использовать UTF-8, а если исключить синтаксический анализатор для недействительного байта, попробуйте повторно его обработать как Windows-1252. 1252, потому что я сомневаюсь, что вы увидите кого-нибудь, использующего символы C1-8859-1 C1, где вы увидите людей, использующих персонажи Windows 1252, и заявляете, что это ISO-8859-1 все время.

Я предлагаю, чтобы SAX принял решение о кодировании, он будет знать это из атрибута кодирования объявления XML

 <?xml version="1.0" encoding="utf-8"?> 

Примечание: если нет объявления xml, которое является законным, тогда предполагается, что кодирование будет UTF-8

Если вы используете байтовый поток InputSource, как в вашем примере, и не устанавливаете явно кодировку InputStream, тогда SAX будет принимать кодировку из XML

ОБНОВИТЬ

Попробуйте этот тест. Он записывает строку xml в файл 1.xml в iso-8859-1. Затем SAX анализирует его и печатает текст корневого элемента (это только один символ «ä»). SAX, как предполагается, не предполагает, что 1.xmk использует iso-8859-1, иначе выход будет искажен

 String xml = "<?xml version='1.0' encoding='iso-8859-1'?><root>ä</root>"; OutputStreamWriter wrt = new OutputStreamWriter(new FileOutputStream( "1.xml"), "iso-8859-1"); wrt.write(xml); wrt.close(); SAXParserFactory sf = SAXParserFactory.newInstance(); SAXParser p = sf.newSAXParser(); p.parse(new FileInputStream("1.xml"), new DefaultHandler() { public void characters(char[] ch, int start, int length) throws SAXException { System.out.println((int)ch[start]); System.out.println(String.valueOf(ch, start, length)); } }); 

См. Вывод

 228 ä 

Верно. SAX скрывает, что XML-кодирование = 'iso-8859-1'.