java - 验证字符串是用 Java 编码的 UTF-8
问题描述
有很多方法可以检查字符串是否为 UTF-8 编码,例如:
public static boolean isUTF8(String s){
try{
byte[]bytes = s.getBytes("UTF-8");
}catch(UnsupportedEncodingException e){
e.printStackTrace();
System.exit(-1);
}
return true;
}
的文档java.lang.String#getBytes(java.nio.charset.Charset)
说:
此方法始终使用此字符集的默认替换字节数组替换格式错误的输入和不可映射的字符序列。
- 它总是返回正确的 UTF-8 字节是否正确?
- 对对象执行此类检查是否有意义
String
?它不会总是true
作为 String 对象返回吗? - 据我了解,此类检查应在字节上执行,而不是在
String
对象上:
public static final boolean isUTF8(final byte[] inputBytes) {
final String converted = new String(inputBytes, StandardCharsets.UTF_8);
final byte[] outputBytes = converted.getBytes(StandardCharsets.UTF_8);
return Arrays.equals(inputBytes, outputBytes);
}
但在这种情况下,我不确定我应该从哪里拿走这些butes,因为直接从String
对象中获取它是不正确的。
解决方案
它总是返回正确的 UTF-8 字节是否正确?
是的。
对 String 对象执行此类检查是否有意义?由于 String 对象已经编码,它不会总是返回 true 吗?
Java 字符串使用以 UTF-16 编码的 Unicode 字符。由于 UTF-16 使用代理项对,任何未配对的代理项都是无效的,因此 Java 字符串可以包含无效char
序列。
Java 字符串还可以包含在 Unicode 中未分配的字符。
这意味着在 Java 上执行验证String
是有意义的,尽管很少这样做。
据我了解,此类检查应在字节上执行,而不是在字符串对象上。
根据字节的字符集,没有什么要验证的,例如字符集 CP437 映射所有 256 字节值,因此它不会无效。
UTF-8 可能无效,因此验证字节很有用是正确的。
正如javadoc所说,getBytes(Charset)
总是用字符集的默认替换字节替换格式错误的输入和不可映射的字符序列。
那是因为它这样做:
CharsetEncoder encoder = charset.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE);
如果您想获取字节,但在格式错误的输入和不可映射的字符序列上失败,请CodingErrorAction.REPORT
改用。因为这实际上是默认值,所以不要调用这两种onXxx()
方法。
例子
String s = "\uD800"; // unpaired surrogate
System.out.println(Arrays.toString(s.getBytes(StandardCharsets.UTF_8)));
打印[63]
的是 a ?
,即未配对的代理是格式错误的输入,因此它被替换为替换字节。
String s = "\uD800"; // unpaired surrogate
CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder();
ByteBuffer encoded = encoder.encode(CharBuffer.wrap(s.toCharArray()));
byte[] bytes = new byte[encoded.remaining()];
encoded.get(bytes);
System.out.println(Arrays.toString(bytes));
这是MalformedInputException: Input length = 1
因为默认的格式错误输入操作是REPORT
.
推荐阅读
- android - 如何在我的 Android 应用中获取 Google 点击 ID (gclid)?
- jquery - InputMask js 显示后端日期
- ionic-framework - 离子对于绘画和绘图应用程序是否足够快?
- numpy - numpy数组中的条件均值?
- html - 如何修复点击时不显示的下拉菜单?
- reactjs - 在 React 中将光标更改为自定义光标
- c# - 如何向 wpf 添加对另一个应用程序的引用,该应用程序已在 powerbuilder 中编写
- php - 如何为子目录配置 .htaccess
- javascript - 使用 fs.mkdir 创建文件夹仅限于只读,因此我无法删除文件夹。节点.js
- c# - Rhino 是否有任何插件或 api 可以将图像直接上传和导入到编辑器