我有一个字节流可能是UTF-8数据,也可能是二进制图像。我应该能够通过检查前100个字节来做出有根据的猜测。
但是,我还没有弄清楚如何在Java中做到这一点。我尝试过以下的事情:
new String(bytes,“UTF-8”)。substring(0,100).matches(“。* [^ \ p {Print}]”)查看前100个字符是否包含不可打印的字符,但是似乎不起作用。
有更好的方法吗?
答案 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;
}