有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么UTF8的新字符串包含更多字节

byte bytes[] = new byte[16];
random.nextBytes(bytes);
try {
   return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
   log.warn("Hash generation failed", e);
}

当我用给定的方法生成一个字符串时,当我应用string.getBytes().length时,它会返回一些其他值。麦克斯32岁。为什么16字节数组最终会生成另一个大小的字节字符串

但如果我这样做string.length(),它会返回16


共 (3) 个答案

  1. # 1 楼答案

    生成的字节可能包含有效的多字节字符

    以此为例。字符串只包含一个字符,但作为字节表示,它需要三个字节

    String s = "Ω";
    System.out.println("length = " + s.length());
    System.out.println("bytes = " + Arrays.toString(s.getBytes("UTF-8")));
    

    String.length()返回字符串的长度(以字符为单位)。字符是一个字符,而在UTF-8中是一个3字节长的字符

    如果你像这样修改代码

    Random random = new Random();
    byte bytes[] = new byte[16];
    random.nextBytes(bytes);
    System.out.println("string = " + new String(bytes, "UTF-8").length());
    System.out.println("string = " + new String(bytes, "ISO-8859-1").length());
    

    相同的字节用不同的字符集进行解释。在String(byte[] b, String charset)的javadoc之后

    The length of the new String is a function of the charset, and hence may
    not be equal to the length of the byte array.
    
  2. # 2 楼答案

    经典错误源于对bytechar之间关系的误解,所以我们再来一遍

    bytechar之间没有1对1的映射;这完全取决于所使用的字符编码(在Java中,即^{

    更糟糕的是:给定一个byte序列,它可能被编码为char序列

    试试这个例子:

    final byte[] buf = new byte[16];
    new Random().nextBytes(buf);
    
    final Charset utf8 = StandardCharsets.UTF_8;
    final CharsetDecoder decoder = utf8.newDecoder()
        .onMalformedInput(CodingErrorAction.REPORT);
    
    decoder.decode(ByteBuffer.wrap(buf));
    

    这很可能会引发MalformedInputException

    我知道这不完全是一个答案,但你没有清楚地解释你的问题;上面的例子已经表明,你对什么是byte和什么是char有错误的理解

  3. # 3 楼答案

    字符串。getBytes()。length可能更长,因为它计算表示字符串所需的字节数,而length()计算2字节的代码单位

    阅读更多here