Ответ 1
Вы не можете сделать это, как только у вас есть строка, вы должны сделать это, пока у вас все еще есть исходный ввод. После того, как у вас есть строка, нет возможности автоматически определить, действительно ли был введен ’
ввод без каких-либо серьезных хрупких тестов. Например:
public static boolean isUTF8MisInterpreted( String input ) {
//convenience overload for the most common UTF-8 misinterpretation
//which is also the case in your question
return isUTF8MisInterpreted( input, "Windows-1252");
}
public static boolean isUTF8MisInterpreted( String input, String encoding) {
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
CharsetEncoder encoder = Charset.forName(encoding).newEncoder();
ByteBuffer tmp;
try {
tmp = encoder.encode(CharBuffer.wrap(input));
}
catch(CharacterCodingException e) {
return false;
}
try {
decoder.decode(tmp);
return true;
}
catch(CharacterCodingException e){
return false;
}
}
public static void main(String args[]) {
String test = "guide (but, yeah, it’s okay to share it with ‘em).";
String test2 = "guide (but, yeah, it’s okay to share it with ‘em).";
System.out.println( isUTF8MisInterpreted(test)); //true
System.out.println( isUTF8MisInterpreted(test2)); //false
}
Если у вас все еще есть доступ к исходному входу, вы можете увидеть, соответствует ли массив байтов полностью действительным последовательностям байтов utf-8 с этим:
public static boolean isValidUTF8( byte[] input ) {
CharsetDecoder cs = Charset.forName("UTF-8").newDecoder();
try {
cs.decode(ByteBuffer.wrap(input));
return true;
}
catch(CharacterCodingException e){
return false;
}
}
Вы также можете использовать CharsetDecoder с потоками, по умолчанию он выдает исключение, как только он видит недопустимые байты в данной кодировке.