【问题标题】:Java String UTF-8 limitsJava 字符串 UTF-8 限制
【发布时间】:2016-09-13 10:14:35
【问题描述】:

我正在尝试直接从文件中反序列化字符串,但我有一个关于超长字符串的问题:Java 字符串的字符数限制等于 Integer.MAX_VALUE,即 31^2-1。

但是我的问题来了:当我有一个 UTF-8 字符串,其大小略小于该大小但由大小超过 1 个字节的字符组成,然后我要求 Java 给我字节数组时会发生什么?

为了更清楚,如果我可以运行这段代码会发生什么? (我没有足够的内存):

String toPrint = "";
String string100 = "";
int max = Integer.MAX_VALUE -100;
for (int i = 0; i < 100; i += 10) {
    string100 += "1234567ñ90";
}
for (int i = 0; i < max; i += 100) {
    toPrint += string100;
}
System.out.println("String complete!");
byte[] byteArray = toPrint.getBytes(StandardCharsets.UTF_8);
System.out.println(byteArray.length);
System.exit(0);

它是否打印“字符串完成!”?还是之前断过?

【问题讨论】:

    标签: java string utf-8 limits


    【解决方案1】:

    从根本上说,Strings 的限制是它们内部的char 数组不能长于最大数组长度,大约是Integer.MAX_VALUE 并且大于您的变量max。字符串以 UTF-16 存储其字符,因此字符串的 UTF-16 表示不能超过最大数组长度。 UTF-8 中的字节数和逻辑字符数(Unicode 代码点或 UTF-32 字符)最终都无关紧要。

    现在让我们转到您的特定示例。由于“1234567ñ90”中的 10 个字符中的每一个都是一个 UTF-16 值,因此该字符串占用了 Stringchar 数组的 10 个值。尽管您的代码性能糟糕且内存要求很高,但它最终应该会达到“字符串完成!”如果有足够的可用内存。但是,在转换为 UTF-8 时会中断,因为字符串的 UTF-8 表示比最大数组长度长,因为“ñ”需要超过一个字节。

    【讨论】:

    • 我同意可怕的表现,这只是概念的证明 XD
    • 但是,Java如何序列化和反序列化呢?因为Java使用UTF-8数组来序列化...
    • @nicovell3 如果字符串序列化调用String.getBytes(UTF-8),将会失败。如果它没有失败,它正在使用另一种方式转换为 UTF-8。
    • 它不使用它,现在我明白为什么了。非常感谢;)
    【解决方案2】:

    数组大小也被限制为Integer.MAX_VALUE(这就是为什么String 的大小是有限的,毕竟有char[] 支持它),所以如果编码使用的字节多于该字节,就不可能得到字节数组, 不管String 的大小是多少。

    最终结果将是 OutOfMemoryError,但首先创建 String 会成功。

    【讨论】:

      猜你喜欢
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-08
      • 2016-07-01
      • 2011-08-16
      • 2018-01-03
      相关资源
      最近更新 更多