【问题标题】:Java substring broken encodingJava 子字符串损坏的编码
【发布时间】:2013-10-19 12:03:18
【问题描述】:

我从 UTF-8 编码的流中读取了一些数据

String line = new String(byteArray, "UTF-8");

然后尝试找到一些子序列

int startPos = line.indexOf(tag) + tag.length();
int endPos   = line.indexOf("/", startPos);

剪下来

String name = line.substring(startPos, endPos);

在大多数情况下它可以正常工作,但有时结果会被破坏。例如,对于像 "гордунни" 这样的输入名称,我得到了像 "горд��нни""горду��ни""г��рдунни" 等这样的值。 似乎代理对由于某种原因被随机破坏。 1000 次中我得到了 4 次。

如何解决?我是否需要使用其他 String 方法而不是 indexOf()+substring() 或对我的结果使用一些编码/解码魔法?

【问题讨论】:

  • 这是linux上的问题吗?你在哪里看“断”线?我在 SWT Table 中遇到了同样的问题,但是当我在 SWT Text 或 Label 中发送此字符串时,它显示正确。最有可能是显示问题。
  • indexOfsubstring 方法确实适用于代码点,因此它们可能会分解代理对,但 гордунни 没有代理对!您确定文本一开始就被正确阅读了吗?
  • 如果在命令行中加上 -Dfile.encoding=UTF-8 会产生同样的结果吗?
  • 这种情况很少发生的事实表明,缓冲区处理代码中的某个地方可能存在错误。您能否使用更长的字符串(可能使用 10.000 个字符)可靠地重现问题?您使用的是哪个版本的 Java?
  • @Joni 谢谢你,你是对的。问题的原因在于我的流处理代码。对于lage InputStream,我用小块读取它,并将每个数组分别转换为String。稍后我会根据需要连接字符串。因此,代理对可以被分割到不同的数组中,稍后的连接将提供这个“破碎”的字符串。如果我将整个 InputStream 转换为一个字符串,问题就会消失。仍然不知道如何用小块来做,但我发现了“断”字符串的原因。谢谢

标签: java utf-8 substring


【解决方案1】:

出现问题是因为流被读取为字节块,有时会拆分多字节 UTF-8 字符。

通过将 InputStream 包装在 InputStreamReader 中,您将读取字符块(而不是字节块),并且多字节 UTF-8 字符将继续存在。

【讨论】:

    【解决方案2】:

    在你的例子中,你能显示字节数组、行和标签的内容吗?您能否还显示将获得什么长度,什么 startPos 和什么 endPos?我的意思是,在字符串“гордунни”中没有“/”!为什么要计算 endPos?标签内的字符串是什么?您确定子字符串的第二个参数是 endpos 而不是长度吗?确实,“гордунни”不需要代理对,因为所有代码点都低于 0xFFFF,但是一旦在您的 utf-16 字符串中的某个地方至少有一个代理对,我敢打赌字符串的长度会给您单词的数量元素而不是代码点的数量。我不确定 Java,但在 C# 中,长度为您提供了元素的数量。要获取字符/代码点的数量,您必须使用 C# 中的 StringInfo 类。还要检查你的字符串中是否有一些 BOM。什么是


    String line = new String(byteArray, "UTF-8");

    在做什么?字节数组是否是一个 utf-8 编码的字符串被转换为 utf-16?它是否包含 utf-8 BOM?之后的字符串是否有 utf-16LE 或 utf-16BE BOM?

    【讨论】:

    • 写关于 BOM 的问题,字符串将被编码为 UTF-16 字符串,只有当 UTF-8 字符串有一个 BOM(根据规范它应该有)时才会有一个 BOM
    猜你喜欢
    • 2021-06-26
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多