Какая хорошая эвристика, чтобы увидеть, кодируется ли набор байтов как UTF-8 в Java? - PullRequest
2 голосов
/ 21 августа 2009

У меня есть поток байтов, который может быть данными UTF-8 или двоичным изображением. Я должен быть в состоянии сделать обоснованное предположение о том, какой из них, проверяя первые 100 байтов или около того.

Однако я не понял, как именно это сделать на Java. Я пытался сделать что-то вроде следующего:

new String (байты, "UTF-8"). Substring (0,100) .matches (". * [^ \ P {Print}]"), чтобы увидеть, если первые 100 символов содержат непечатаемые символы, но это не похоже на работу.

Есть ли лучший способ сделать это?

Ответы [ 4 ]

4 голосов
/ 21 августа 2009

В правильно сформированном UTF-8 за байтом с установленным верхним битом должен следовать или предшествовать другой байт с установленным верхним битом; первый цикл должен начинаться с двух верхних установленных битов, а остальные должны иметь очищенный бит сверху-вниз (на самом деле первый цикл из N старших байтов должен иметь установленные верхние N битов и следующий одно ясно).

Эти характеристики должны быть достаточно легкими для поиска.

3 голосов
/ 21 августа 2009
    final Charset charset = Charset.forName("UTF-8");
    final CharsetDecoder decoder = charset.newDecoder();
    decoder.onMalformedInput(CodingErrorAction.REPORT);

    try {
        final String s = decoder.decode(ByteBuffer.wrap(bytes)).toString();
        Log.d( s );
    } catch( CharacterCodingException e ) {
        // don't log binary data
    }
0 голосов
/ 16 июля 2018

Вот более простая / понятная версия ответа emmby для (возможно, огромного) потока байтов:

/**
 * Determines whether the stream is valid UTF-8  
 * @param is InputStream (will be closed)
 * @return true if it's valid UTF-8 , false elsewhere
 * @throws IOException Only for other I/O problems
 */
public static boolean isUtf8(InputStream is) throws IOException {
    final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
    decoder.onMalformedInput(CodingErrorAction.REPORT);
    final int CHARS = 8192;
    final char[] cbuf = new char[CHARS];
    try (InputStreamReader isr = new InputStreamReader(is, decoder)) {
        while(isr.read(cbuf) > 0) {
        }
    } catch(CharacterCodingException e) {
        return false;
    } 
    return true;
}
0 голосов
/ 21 августа 2009

Я предлагаю использовать ICU4J

ICU - это зрелый, широко используемый набор библиотек C / C ++ и Java, обеспечивающий поддержку Unicode и Globalization для программных приложений. ICU широко переносим и дает приложениям одинаковые результаты на всех платформах и между C / C ++ и программным обеспечением Java.

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