Java子串打破编码

我用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()或在我的结果上使用一些编码/解码魔术?

为了从“未答复”队列中获取此信息。

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

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

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

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

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