如何在Java中将一组字节编码为UTF-8,这是一个很好的启发式算法?

时间:2009-08-20 23:06:48

标签: java utf-8

我有一个字节流可能是UTF-8数据,也可能是二进制图像。我应该能够通过检查前100个字节来做出有根据的猜测。

但是,我还没有弄清楚如何在Java中做到这一点。我尝试过以下的事情:

new String(bytes,“UTF-8”)。substring(0,100).matches(“。* [^ \ p {Print}]”)查看前100个字符是否包含不可打印的字符,但是似乎不起作用。

有更好的方法吗?

4 个答案:

答案 0 :(得分:4)

在格式良好的UTF-8中,必须在最高位设置的字节之前或之前设置最高位的另一个字节;运行的第一个必须从设置的两个最高位开始,其余的必须清除下一个到顶部的位(事实上,N个顶部位字节的第一个必须设置前N位和下一个一个明确的。)

这些特征应该很容易找到。

答案 1 :(得分:3)

    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
    }

答案 2 :(得分:0)

我建议使用ICU4J

  

ICU是一套成熟且广泛使用的C / C ++和Java库,为软件应用程序提供Unicode和全球化支持。 ICU具有广泛的可移植性,可以在所有平台上以及C / C ++和Java软件之间为应用程序提供相同的结果。

答案 3 :(得分:0)

这是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;
}