gpt4 book ai didi

java - 验证字符串是用 Java 编码的 UTF-8

转载 作者:行者123 更新时间:2023-11-29 04:05:28 29 4
gpt4 key购买 nike

有很多关于如何检查字符串是否为 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) 的文档说:

This method always replaces malformed-input and unmappable-character sequences with this charset's default replacement byte array.

  1. 它总是返回正确的 UTF-8 字节是否正确?
  2. String 对象执行这样的检查是否有意义?它不会总是返回 true 因为 String 对象已经编码了吗?
  3. 据我所知,此类检查应该对字节执行,而不是对 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 对象获取它是不正确的。

最佳答案

Is it correct that it always returns correct UTF-8 bytes?

是的。

Does it make sense to perform such checks on String objects at all? Won't it always be returning true as a String object is already encoded?

Java 字符串使用以 UTF-16 编码的 Unicode 字符。由于 UTF-16 使用代理对,任何未配对的代理都是无效的,因此 Java 字符串可以包含无效的 char 序列。

Java 字符串还可以包含在 Unicode 中未分配的字符。

这意味着对 Java String 执行验证是有意义的,尽管很少有人这样做。

As far as I understand such checks should be performed on bytes, not on String objects.

根据字节的字符集,没有什么需要验证的,例如字符集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] 是一个 ?,即未配对的代理项是格式错误的输入,因此它被替换为替换字节。

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

关于java - 验证字符串是用 Java 编码的 UTF-8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59094164/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com