StringEscapeUtils不能处理UTF-8编码问题。

6

我有一个类似这样的字符串

String incoming = "<html> <head></head> <body>  <p><span style=\"font-family: Arial;\">Ευχαριστώ (eff-kha-ri-STOE) Tι κανείς (tee-KAH-nis)? Mε συγχωρείτε.</span></p> </body></html>";

我正在使用StringEscapeUtils进行转义

import org.apache.commons.text.StringEscapeUtils;
String escaped = StringEscapeUtils.escapeJava(incoming);

结果是。
<html> <head></head> <body>  <p><span style=\"font-family: Arial;\">\u0395\u03C5\u03C7\u03B1\u03C1\u03B9\u03C3\u03C4\u03CE (eff-kha-ri-STOE) T\u03B9 \u03BA\u03B1\u03BD\u03B5\u03AF\u03C2 (tee-KAH-nis)? M\u03B5 \u03C3\u03C5\u03B3\u03C7\u03C9\u03C1\u03B5\u03AF\u03C4\u03B5.</span></p> </body></html>

我尝试过将它转换成 utf-8 编码,使用了字节编码,但是没有成功。有没有其他方法可以修复这个问题呢?
这是我的尝试代码:
String s = new String(escaped.getBytes("UTF-8"), "UTF-8");
我还尝试了另外一个库来进行文本转义,但是仍然没有成功。
1个回答

9

我假设您想要对输入的String中的单引号、双引号和反斜杠等字符进行转义,但希望希腊字符保持不变。

不幸的是,StringEscapeUtils.escapeJava()将任何Unicode值>0x7f的文本字符转换为它们的Unicode转义等效项。例如,您的示例数据显示,希腊字母tau(τ)在StringEscapeUtils.escapeJava()返回的字符串中被转义为\u03C4。我不知道为什么escapeJava()会这样做。 其Javadoc指出“使用Java字符串规则转义字符串中的字符。”,但我找不到“Java字符串规则”的正式定义。

消除StringEscapeUtils.escapeJava()返回的字符串中的Unicode转义的简单方法是调用UnicodeUnescaper类的translate()方法

将形式为\u+\d\d\d\d的转义Unicode值转换回Unicode。它支持多个'u'字符,并可用于带有或不带'+'的情况。

因此,调用UnicodeUnescaper.translate()将返回一个String,该字符串:

  • 保留字符串中的转义字符,例如双引号,不做任何修改。
  • 将Unicode文字替换为它们的希腊字符等效项。例如,\u03C4将被更改为τ

代码很简单。使用您的数据:

import org.apache.commons.text.StringEscapeUtils;
import org.apache.commons.text.translate.UnicodeUnescaper;

void convert() {
    String incoming = "<html> <head></head> <body>  <p><span style=\"font-family: Arial;\">Ευχαριστώ (eff-kha-ri-STOE) Tι κανείς (tee-KAH-nis)? Mε συγχωρείτε.</span></p> </body></html>";
    String escaped = StringEscapeUtils.escapeJava(incoming); 
    String greekChars = new UnicodeUnescaper().translate(escaped);

    System.out.println("incoming:   " + incoming); 
    System.out.println("escaped:    " + escaped);    // Quotes are escaped, and Greek characters are converted to Unicode escapes.
    System.out.println("greekChars: " + greekChars); // Quotes remain escaped, but Unicode escapes are converted back to Greek characters.
}

这是println()调用的输出结果:
run:
incoming:   <html> <head></head> <body>  <p><span style="font-family: Arial;">Ευχαριστώ (eff-kha-ri-STOE) Tι κανείς (tee-KAH-nis)? Mε συγχωρείτε.</span></p> </body></html>
escaped:    <html> <head></head> <body>  <p><span style=\"font-family: Arial;\">\u0395\u03C5\u03C7\u03B1\u03C1\u03B9\u03C3\u03C4\u03CE (eff-kha-ri-STOE) T\u03B9 \u03BA\u03B1\u03BD\u03B5\u03AF\u03C2 (tee-KAH-nis)? M\u03B5 \u03C3\u03C5\u03B3\u03C7\u03C9\u03C1\u03B5\u03AF\u03C4\u03B5.</span></p> </body></html>
greekChars: <html> <head></head> <body>  <p><span style=\"font-family: Arial;\">Ευχαριστώ (eff-kha-ri-STOE) Tι κανείς (tee-KAH-nis)? Mε συγχωρείτε.</span></p> </body></html>
BUILD SUCCESSFUL (total time: 0 seconds)

注意事项:

  • 请务必使用org.apache.commons.text.translate包中的UnicodeUnescaper。旧版本已过时,存在于org.apache.commons.lang3.text.translate包中。这是Apache Commons Text下载页面的链接,当前版本为1.8。
  • 这并不是一个理想的解决方案,因为它调用了UnicodeUnescaper.translate()来修复由StringEscapeUtils.escapeJava()创建的混乱。可能还有其他更简洁的方法(使用StringEscapeUtils.escapeJava()的替代方法),但这种方法似乎对您的数据效果很好。

谢谢,这对我的使用情况非常有效。它修复了escapeJava()引起的混乱。 - Shashank
1
@orcluser [1] 正如我在答案中引用的那样,UnicodeUnescaper.translate()将把形式为“\u+\d\d\d\d”的转义Unicode值转换回Unicode。但是,您传递给translate()的字符串(即“für”)不是这种形式。 - skomisa
1
@orcluser...[2] 还要注意,escapeHtml() 的 Javadoc 表明它会使用 HTML 实体转义字符串中的字符,并且这正是您的示例中发生的情况:“ü”已正确转义为“**ü**”。因此,您的问题与使用德语字符无关。如果可行的话,也许尝试将对 escapeHtml() 的调用替换为对 escapeJava() 的调用来解决您的问题? - skomisa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接