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?