Как удалить символы с диакритикой из InputStream

Я пытаюсь проанализировать Rss2.0, питаются Android с помощью синтаксического анализатора Получения по запросу.

XmlPullParser parser = Xml.newPullParser();
parser.setInput(url.open(), null);

Пролог канала, XML заявляет, что кодирование является "utf-8". Когда я открываю удаленный поток и передаю это моему Синтаксическому анализатору Получения по запросу, я получаю недопустимый маркер, документ не хорошо сформированные исключения.

Когда я сохраняю XML-файл и открываю его в браузере (Firefox), браузер сообщает о присутствии символа Unicode 0x12 (серьезный диакритический знак?) в файле и сбоях для рендеринга XML.

Что лучший способ состоит в том, чтобы обработать такие случаи, предполагающие, что я не имею никакого контроля над XML тем, чтобы быть возвращенным?

Спасибо.

5
задан Samuh 18 May 2010 в 09:29
поделиться

5 ответов

Откуда вы взяли, что 0x12 - это могильное ударение? В UTF-8 диапазон символов 0x00-0x7F кодируется так же, как и в ASCII, а кодовая точка ASCII 0x12 - это управляющий символ, DC2, или CTRL+R.

Похоже, что это какая-то проблема с кодировкой. Самый простой способ решить эту проблему - посмотреть на сохраненный файл в шестнадцатеричном редакторе. Есть некоторые вещи, которые нужно проверить:

  1. метка порядка байтов (BOM) в начале может сбить с толку некоторые анализаторы XML
  2. даже если в декларации XML указано, что кодировка UTF-8, на самом деле она может не иметь такой кодировки, и файл будет декодирован неправильно.
  3. не все символы юникода являются законными в XML, поэтому firefox отказывается его отображать. В частности, спецификация XML гласит, что 0x9, 0xA и 0xD являются единственными допустимыми символами меньше 0x20, поэтому 0x12 определенно вызовет недовольство совместимых парсеров.

Если вы можете загрузить файл на pastebin или аналогичный ресурс, я могу помочь найти причину и предложить решение.

EDIT: Хорошо, вы не можете загрузить. Это понятно.

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

Однако, прежде чем это сделать, следует кое-что проверить - уверены ли вы, что получаете данные без повреждений? Некоторые формы связи (SMS) допускают только 7-битные символы. Это превратит 0x92 (ASCII forward tick/apostrophe - grave accent?) в 0x12. Похоже на совпадение, особенно если они появляются в файле, где вы ожидали бы ударение.

В противном случае, вам придется попытаться обойтись тем, что есть:

  1. хотя это и не является строго необходимым, защититесь и передайте "UTF-8" в качестве второго параметра в setInput парсера.

  2. Аналогично, заставьте синтаксический анализатор использовать другую кодировку символов, передав другую кодировку в качестве второго параметра. В дополнение к "UTF-8" можно попробовать кодировки "iso-8859-1" и "UTF-16". Полный список поддерживаемых кодировок для java приведен на сайте Sun - вы можете попробовать все из них. (Я не смог найти точного списка поддерживаемых кодировок для Android).

  3. В крайнем случае, вы можете удалить недопустимые символы, например, удалить все символы ниже 0x20, которые не являются пробелами (0x9, 0xA и 0xD - все пробелы). Если удалить их сложно, вы можете заменить их.

Например

class ReplacingInputStream extends FilterInputStream
{
   public int read() throws IOException
   {
      int read = super.read();
      if (read!=-1 && read<0x20 && !(read==0x9 || read==0xA || read==0xB))
         read = 0x20;
      return read;          
   }
}

Вы оборачиваете это вокруг существующего входного потока, и он отфильтровывает недопустимые символы. Обратите внимание, что вы легко можете нанести XML еще больший ущерб или получить в итоге бессмысленный XML, но в равной степени это может позволить вам получить нужные данные или легче увидеть, где кроются проблемы.

6
ответ дан 13 December 2019 в 19:23
поделиться

Я использую для фильтрации его с помощью регулярного выражения, но хитрость не пытается получить и сменить акценты. Это зависит от кодировки, и вы не хотите изменять содержимое.

Попробуйте вставить содержимое тегов в эти теги

Вот так

<title>My title</title>
<link>http://mylink.com</link>
<description>My description</description>

К этому

<title><![CDATA[My title]]></title>
<link><![CDATA[http://milynk.com]]></link>
<description><![CDATA[My Description]]></description>

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

2
ответ дан 13 December 2019 в 19:23
поделиться

Вызов setInput(istream, null) уже означает для pull-парсера попытку самостоятельно определить кодировку. Очевидно, что это не удается, поскольку существует реальная проблема с файлом. Так что это не значит, что ваш код неправильный - нельзя ожидать, что вы сможете разобрать все неправильные документы, будь то неправильно сформированные или с неправильными кодировками.

Однако если вы обязательно должны попытаться разобрать этот конкретный документ, вы можете изменить свой код разбора так, чтобы он находился в функции, принимающей кодировку в качестве параметра и заключенной в блок try/catch. В первый раз не указывайте кодировку, и если вы получите ошибку кодировки, запустите ее заново с ISO-8859-1. Если успех обязателен, повторите для других кодировок, в противном случае после двух попыток прекратите работу.

1
ответ дан 13 December 2019 в 19:23
поделиться

Проблема с UTF-8 в том, что это многобайтовая кодировка. Таким образом, ему нужен способ указать, когда символ образован более чем одним байтом (может быть, два, три, четыре, ...). Для этого нужно зарезервировать некоторые байтовые значения для сигнализации многобайтовых символов. Таким образом, кодирование следует некоторым основным правилам:

  • Однобайтовые символы не имеют набора MSB (коды, совместимые с 7-битным ASCII).
  • Два байтовых символа представлены последовательностью: 110xxxxx 10xxxxxx
  • Три байта: 1110xxxx 10xxxxxx 10xxxxxx
  • Четыре байта: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Ваша проблема в том, что вы, возможно, читаете строку символов закодирован как UTF-8 (как указано в определении кодировки XML), но байтовый фрагмент может быть на самом деле не закодирован в UTF-8 (распространенная ошибка - объявлять что-то как UTF-8, но кодировать текст с другой кодировкой, например как Cp1252).Ваш XML-синтаксический анализатор пытается интерпретировать байтовые блоки как символы UTF-8, но находит что-то, что не соответствует правилам кодирования (недопустимый символ). Т.е. два байта с двумя самыми значительными наборами байтов вызовут недопустимую ошибку кодирования: за 110xxxxx всегда должно следовать 10xxxxxx (такие значения, как 01xxxxxx 11xxxxxx 00xxxxxx, будут недопустимыми).

Эта проблема не возникает, когда используются кодировки без переменной длины. Т.е. если вы укажете в своем XML-объявлении, что ваш файл использует кодировку Windows-1252, но в конечном итоге вы используете ANSI, ваша единственная проблема будет заключаться в том, что символы, отличные от ASCII (значения> 127), будут отображаться неправильно.


Решение:

  1. Попробуйте определить кодировку другими способами .
    • Если вы всегда будете читать данные из одного и того же источника, вы можете выбрать несколько файлов и использовать расширенный текстовый редактор, который пытается вывести фактическую кодировку файла (например, notepad ++ , jEdit и т. Д.).
    • Делайте это программно. Предварительно обработайте необработанные байты перед выполнением какой-либо фактической обработки xml.
  2. Принудительное фактическое кодирование в процессоре XML

В качестве альтернативы, если вы не возражаете против символов, отличных от ASCII (независимо от того, появляются ли странные символы время от времени), вы можете сразу перейти к шагу 2 и принудительно применяет обработку XML к любой 8-байтовой кодировке фиксированной длины, совместимой с ASCII (ANSI, любая кодовая страница Windows-XXXX, кодировка Mac-Roman и т. Д.). С вашим нынешним кодом вы можете просто попробовать:

XmlPullParser parser = Xml.newPullParser();
parser.setInput(url.open(), "ISO-8859-1");
2
ответ дан 13 December 2019 в 19:23
поделиться

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

0
ответ дан 13 December 2019 в 19:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: