Я имею UTF-8 - но все еще получаю "Неверный байт 1 последовательности 1-байтового UTF-8" - PullRequest
6 голосов
/ 12 декабря 2011

Я создаю строку XML на лету (НЕ читая из файла). Затем я использую Cocoon 3, чтобы преобразовать его через FOP в PDF. Где-то посередине бегает Xerces. Когда я использую жестко закодированные вещи, все работает. Как только я помещаю немецкий умлаут в базу данных и обогащаю свой xml этими данными, я получаю:

Caused by: org.apache.cocoon.pipeline.ProcessingException: Can't parse the XML string.
at org.apache.cocoon.sax.component.XMLGenerator$StringGenerator.execute(XMLGenerator.java:326)
at org.apache.cocoon.sax.component.XMLGenerator.execute(XMLGenerator.java:104)
at org.apache.cocoon.pipeline.AbstractPipeline.invokeStarter(AbstractPipeline.java:146)
at org.apache.cocoon.pipeline.AbstractPipeline.execute(AbstractPipeline.java:76)
at de.grobmeier.tab.webapp.modules.documents.InvoicePipeline.generateInvoice(InvoicePipeline.java:74)
... 87 more

Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence.
    at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:684)
    at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:554)

Затем я отладил свое приложение и обнаружил, что мой «Ä» (который поступает из базы данных) имеет значение байта 196, то есть C4 в шестнадцатеричном формате. Вот что я ожидал в соответствии с этим: http://www.utf8 -zeichentabelle.de /

Я не знаю, почему мой код не работает.

Затем я попытался добавить спецификацию вручную, например:

byte[] bom = new byte[3];
bom[0] = (byte) 0xEF;
bom[1] = (byte) 0xBB;
bom[2] = (byte) 0xBF;
String myString = new String(bom) + inputString;

Я знаю, что это не совсем хорошо, но я попробовал - конечно, это не удалось. Я попытался добавить заголовок xml перед:

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

Что тоже не удалось. Тогда я объединил это. Не удалось.

В конце концов я попробовал что-то подобное:

xmlInput = new String(xmlInput.getBytes("UTF8"), "UTF8");

Что на самом деле ничего не делает, потому что это уже UTF-8. Тем не менее это не удается.

Итак ... есть идеи, что я делаю неправильно и чего от меня ожидает Ксерс?

Спасибо Christian

Ответы [ 3 ]

13 голосов
/ 12 декабря 2011

Если ваша база данных содержит только один байт (со значением 0xC4), то вы не используете кодировку UTF-8.

Символ «LATIN CAPITAL LETTER A WITH DIAERESIS» имеет значение кодовой точки U + 00C4, но UTF-8 не может кодировать его в одном байте. Если вы проверите третий столбец «UTF-8 (hex.)» На UTF8-zeichentabelle.de, вы увидите, что UTF-8 кодирует его как 0xC3 84 (два байта).

Пожалуйста, прочитайте статью Джоэла " Абсолютный минимум, который должен знать каждый разработчик программного обеспечения. Абсолютно, положительно должен знать о Unicode и наборах символов (без оправданий!) " для получения дополнительной информации.


РЕДАКТИРОВАТЬ: Кристиан сам нашел ответ; Оказалось, что это была проблема в компоненте Cocoon 3 SAX (я думаю, что это версия альфа 3). Оказывается, что если вы передадите XML в виде String в класс XMLGenerator, во время синтаксического анализа SAX что-то пойдет не так, что приведет к этому беспорядку.

Я посмотрел код , чтобы найти актуальную проблему в Cocoon-stax:

if (XMLGenerator.this.logger.isDebugEnabled()) {
    XMLGenerator.this.logger.debug("Using a string to produce SAX events.");
}
XMLUtils.toSax(new ByteArrayInputStream(this.xmlString.getBytes()), XMLGenerator.this.getSAXConsumer();

Как вы можете видеть, вызов getBytes() создаст байтовый массив с кодировкой JRE по умолчанию, который затем не удастся проанализировать. Это потому, что XML объявляет себя UTF-8, тогда как данные теперь снова в байтах и, вероятно, используют вашу кодовую страницу Windows.

В качестве обходного пути можно использовать следующее:

new org.apache.cocoon.sax.component.XMLGenerator(xmlInput.getBytes("UTF-8"),
       "UTF-8");

Это вызовет правильные внутренние действия (как выяснил Кристиан, экспериментируя с API).

Я открыл проблему в баг-трекере Apache.

РЕДАКТИРОВАТЬ 2: проблема исправлена ​​и будет включена в следующий выпуск.

2 голосов
/ 12 декабря 2011

C4, который вы видите на этой странице, относится к кодовой точке Unicode, U+00C4.Последовательность байтов, используемая для представления такой кодовой точки в UTF-8, НЕ "\xC4".То, что вы хотите, это то, что находится в столбце UTF-8 (шестнадцатеричный), а именно "\xC3\x84".

Следовательно, ваши данные не в UTF-8.здесь кодируется в UTF-8 .

0 голосов
/ 03 февраля 2016

Я использую Windows 7 с TextPad в качестве текстового редактора для создания файла данных xml вручную. Я получал MalformedByteSequenceException. Моя спецификация в XML-файле была UTF-8. Покопавшись, я обнаружил, что в моем редакторе есть инструмент "Инструменты ... Преобразовать в DOS". Я сделал это, повторно сохранил файл, и исключение исчезло, и мой код работал нормально.

Затем я посмотрел кодировку по умолчанию для этого типа файлов в моем редакторе. Это был ASCII, хотя, когда я изменил параметр кодирования xml на ASCII, я получил еще один MalformedByteSequenceException.

Таким образом, в системах Windows вы можете попытаться сохранить кодировку XML в UTF-8, но сохранить файл в кодировке DOS. Я не стал больше копать, почему это работает.

...