我正在使用“*org.apache.commons.lang.StringEscapeUtils.unescapeHtml(myHtmlString)”将 Html 实体转义转换为包含与转义对应的实际 Unicode 字符的字符串。但是它不能正确解析“em dash”和“en dash”符号。StringEscapeUtils 将“–”替换为“\u0096”,而正确的错位是“\u2013”。正如我所读到的,“\u0096”相当于“-”的 cp1252。那么我怎样才能让它以正确的方式工作呢?我知道我可以手动替换它,但我想知道是否可以使用 StringEscapeUtils 或任何其他实用程序来替换它。
2 回答
我怀疑问题不在StringEscapeUtils.unescapeHtml(...)
通话中。
'\u0096'
相反,我怀疑角色在通话之前已经变成了。更具体地说,我怀疑您的代码在将 HTML 作为字符读取时使用了错误的字符集。
正如您所说,短划线是0x96
cp1252 中的代码点。因此,将破折号错误翻译为 unicode 代码点的一种方法\u0096
是从使用 cp1252 编码的字节流开始,然后使用InputStreamReader(is, "Latin-1")
.
And as I have read "\u0096" is cp1252 equivalent for "–".
我不这么认为。Unicode 中的 0x0096 是 C1 控制代码:
http://en.wikipedia.org/wiki/C0_and_C1_control_codes
并且不太可能替代“-”(如您所写)。
好吧,如果StringEscapeUtils真的把它搞砸了(破折号确实应该是 \u2013)并且如果它是唯一的转义它就是搞砸了,如果没有理由在你的 String 中有任何其他 0x0096,那么调用StringEscapeUtils之后的replaceAll 应该可以工作.
以下是您期望的替换:
System.out.println("Broken\u0096stuff".replaceAll("\u0096", "\u2013"));
但是,您应该首先确保StringEscapeUtils真的把事情搞砸了,并且真的,真的,理解为什么/如何在 Java 字符串中得到那个 0x0096。
然后,还应该向您指出,遗憾的是 Java 的 Unicode 支持是一个主要的 SNAFU,因为 Java 是在 Unicode 3.1 出现之前构思的。
因此,对char原语使用 16 位似乎是一个聪明的主意,使用 4 位十六进制数字 '\uxxxx' 转义序列似乎是一个聪明的主意,用字符串的长度表示char[]的长度似乎是一个聪明的主意() 方法等
这些实际上都是非常非常愚蠢的想法,导致了主要的 Java SNAFU 之一,其中char原语实际上不能再保存 Unicode 字符,并且 String 的 length 方法实际上不返回 String 的实际长度。
我喜欢以下内容:
final char brokenCharCannotRepresentUnicode31Codepoints = '\uFFFF'; // How do I store a Unicode 3.1 codepoint here!?
为什么要这样吐槽?好吧,因为我不知道 String 的replaceAll中的正则表达式替换是如何实现的,但是如果在某些情况下(即某些代码点)String 的replaceAll像char和像length和像\uxxxx一样,我真的不会感到惊讶.. 嗯,完全坏了。