удалить символы не-UTF-8 из xml с объявленной кодировкой = utf-8 - Java - PullRequest
16 голосов
/ 20 мая 2010

Я должен обработать этот сценарий в Java:

Я получаю запрос в формате XML от клиента с объявленной кодировкой = utf-8. К сожалению, он может содержать не utf-8 символов, и есть требование удалить эти символы из xml на моей стороне (наследие).

Давайте рассмотрим пример, где этот неверный XML содержит £ (фунт).

1) Я получаю XML как строку Java с символом £ (сейчас у меня нет доступа к интерфейсу, но я, вероятно, получаю XML как строку Java) Могу ли я использовать replaceAll (£, ""), чтобы избавиться от этого персонажа? Есть потенциальные проблемы?

2) Я получаю XML в виде массива байтов - как безопасно выполнить эту операцию в этом случае?

Ответы [ 6 ]

25 голосов
/ 20 мая 2010

1) Я получаю XML как строку Java с символом £ (сейчас у меня нет доступа к интерфейсу, но я, вероятно, получаю строку XML как строку Java). Могу ли я использовать replaceAll (£, ""), чтобы избавиться от этого персонажа?

Я предполагаю, что вы скорее имеете в виду, что вы хотите избавиться от не- ASCII символов, потому что вы говорите о "унаследованной" стороне. Вы можете избавиться от всего, что находится за пределами диапазона печати ASCII , используя следующее регулярное выражение:

string = string.replaceAll("[^\\x20-\\x7e]", "");

2) Я получаю XML в виде массива байтов - как безопасно выполнить эту операцию в этом случае?

Вам необходимо обернуть byte[] в ByteArrayInputStream, чтобы их можно было прочитать в потоке символов в кодировке UTF-8, используя InputStreamReader, в котором вы указываете кодирование, а затем используйте BufferedReader, чтобы прочитать его построчно.

1028 * Е.Г. *

BufferedReader reader = null;
try {
    reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8"));
    for (String line; (line = reader.readLine()) != null;) {
        line = line.replaceAll("[^\\x20-\\x7e]", "");
        // ...
    }
    // ...
17 голосов
/ 20 мая 2010

UTF-8 - кодировка; Юникод это набор символов. Но символ GBP наиболее определенно присутствует в наборе символов Unicode и, следовательно, наверняка представлен в UTF-8.

Если вы на самом деле имеете в виду UTF-8, и вы на самом деле пытаетесь удалить байтовые последовательности, которые не являются допустимой кодировкой символа в UTF-8, то ...

CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
ByteBuffer bytes = ...;
CharBuffer parsed = utf8Decoder.decode(bytes);
...
7 голосов
/ 27 октября 2011
"test text".replaceAll("[^\\u0000-\\uFFFF]", "");

Этот код удаляет все 4-байтовые символы utf8 из строки. Это может понадобиться для некоторых целей при выполнении записи Mysql innodb varchar

3 голосов
/ 23 июня 2011

Я столкнулся с той же проблемой при чтении файлов из локального каталога и попробовал это:

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document xmlDom = db.parse(new InputSource(in));

Возможно, вам придется использовать сетевой входной поток вместо FileInputStream.

- Капил

2 голосов
/ 02 июня 2013

Обратите внимание, что первым шагом должно быть то, что вы просите создателя XML (который, скорее всего, является домашним генератором XML "просто распечатать данные"), чтобы убедиться, что их XML верен перед отправкой вам. Самый простой из возможных тестов, если они используют Windows, - попросить их просмотреть его в Internet Explorer и увидеть ошибку синтаксического анализа в первом оскорбительном символе.

Пока они это исправляют, вы можете просто написать небольшую программу, которая изменит часть заголовка, чтобы объявить вместо этого кодировку ISO-8859-1:

<?xml version="1.0" encoding="iso-8859-1" ?>

и оставьте остальное нетронутым.

1 голос
/ 27 мая 2015

Как только вы преобразуете байтовый массив в String на Java-машине, вы получите (по умолчанию на большинстве машин) строку в кодировке UTF-16. Правильное решение, чтобы избавиться от символов, отличных от UTF-8, с помощью следующего кода:

String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa"};
for (int i = 0; i < values.length; i++) {
    System.out.println(values[i].replaceAll(
                    "[\\\\x00-\\\\x7F]|" + //single-byte sequences   0xxxxxxx
                    "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences   110xxxxx 10xxxxxx
                    "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences   1110xxxx 10xxxxxx * 2
                    "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3
            , ""));
}

или если вы хотите проверить, содержит ли какая-либо строка не utf8 символы, вы должны использовать Pattern.matches, например:

String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa"};
for (int i = 0; i < values.length; i++) {
    System.out.println(Pattern.matches(
                    ".*(" +
                    "[\\\\x00-\\\\x7F]|" + //single-byte sequences   0xxxxxxx
                    "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences   110xxxxx 10xxxxxx
                    "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences   1110xxxx 10xxxxxx * 2
                    "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3
                    + ").*"
            , values[i]));
}

Если у вас есть доступный байтовый массив, вы можете отфильтровать их еще более правильно с помощью:

BufferedReader bufferedReader = null;
try {
    bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8"));
    for (String currentLine; (currentLine = bufferedReader.readLine()) != null;) {
        currentLine = currentLine.replaceAll(
                        "[\\x00-\\x7F]|" + //single-byte sequences   0xxxxxxx
                        "[\\xC0-\\xDF][\\x80-\\xBF]|" + //double-byte sequences   110xxxxx 10xxxxxx
                        "[\\xE0-\\xEF][\\x80-\\xBF]{2}|" + //triple-byte sequences   1110xxxx 10xxxxxx * 2
                        "[\\xF0-\\xF7][\\x80-\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3
                , ""));
    }

Чтобы сделать все веб-приложение совместимым с UTF8, прочитайте здесь:
Как заставить UTF-8 работать в веб-приложениях Java
Подробнее о байт-кодировках и строках .
Вы можете проверить свой шаблон здесь .
То же самое в PHP здесь .

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