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

问题描述 投票:1回答:1

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

此方法始终使用此字符集的默认替换字节数组替换格式错误的输入和不可映射的字符序列。

  1. 它总是返回正确的UTF-8字节是否正确?
  2. 完全对String对象执行这种检查是否有意义?因为一个String对象已经被编码,它是否总会返回true
  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);
}

但是在这种情况下,我不确定我应该从哪里获取这些脚印,因为直接从String对象获取它是不正确的。

java string encoding utf-8 utf-16
1个回答
0
投票

它总是返回正确的UTF-8字节是否正确?

根本不对String对象执行这种检查是否有意义?难道由于String对象已经被编码,它是否总是返回true?

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

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

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

据我所知,此类检查应在字节上执行,而不是在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],即?,即未配对的代理输入格式错误,因此将其替换为替换字节。

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

© www.soinside.com 2019 - 2024. All rights reserved.