Подтвердить что ты не робот

Как обнаружить незаконные последовательности байтов UTF-8 для их замены в java inputstream?

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

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

Это непростая задача, она думает, что для этого требуется некоторое знание о конечной машине UTF-8.

Oracle имеет оболочку, которая делает то, что мне нужно:
UTF8ValidationFilter javadoc

Есть ли что-то подобное (коммерчески или бесплатно)?

Спасибо
-stephan

Решение:

final BufferedInputStream in = new BufferedInputStream(istream);
final CharsetDecoder charsetDecoder = StandardCharsets.UTF_8.newDecoder();
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE);
charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
final Reader inputReader = new InputStreamReader(in, charsetDecoder);
4b9b3361

Ответ 1

java.nio.charset.CharsetDecoder делает то, что вам нужно. Этот класс обеспечивает кодирование символов с определяемыми пользователем действиями при различных видах ошибок (см. onMalformedInput() и onUnmappableCharacter()).

CharsetDecoder записывается в OutputStream, который вы можете передать в InputStream с помощью java.io.PipedOutputStream, эффективно создавая фильтрованный InputStream.

Ответ 2

Один из способов - прочитать первые несколько байтов, чтобы проверить отметку порядка байтов (если существует). Дополнительная информация о спецификации: http://en.wikipedia.org/wiki/Byte_order_mark В данном URL-адресе вы найдете таблицу байтов спецификации. Однако одна из проблем заключается в том, что UTF-8 не требует использования спецификации в своем "заголовке". Существует еще один способ решения проблемы - распознавание образов (каждый раз считывается несколько байтов-8 бит). Во всяком случае, это сложное решение.

Ответ 3

Поведение, которое вы хотите, уже по умолчанию для InputStreamReader. Поэтому нет необходимости указывать его самостоятельно. Этого достаточно:

final BufferedInputStream in = new BufferedInputStream(istream);
final Reader inputReader = new InputStreamReader(in, StandardCharsets.UTF_8);