将转义的Unicode字符转换回实际字符

35

我在Java中的字符串变量中有以下值,其中包含UTF-8编码的字符,如下所示

Dodd\u2013Frank

而不是

Dodd–Frank

假设我无法控制将该值分配给此字符串变量的方式。

现在,我该如何正确地转换(编码)它并将其存储回一个String变量中?

我找到了以下代码:

Charset.forName("UTF-8").encode(str);

但是这会返回一个ByteBuffer,而我想要一个String

编辑:

一些额外的信息。

当我使用System.out.println(str);时,我得到的是

Dodd\u2013Frank

我不确定什么是正确的术语(UTF-8还是Unicode)。请见谅。


1
我对这个问题不是很清楚。当您输入System.out.println(yourString);时,您看到的是(1)Dodd\u2013Frank还是(2)Dodd–Frank - jlordo
7
错误,\u2013不是一个UTF-8字符,它是一个转义的Unicode字符。UTF-8是一种编码UTF字符的方式。 - SirDarius
@jlordo和SirDarius,我已经更新了问题并添加了详细信息。 - Sudar
4
请查看 StringEscapeUtils.unescapeJava()。该方法可用于将 Java 字符串中的转义字符还原为它们所代表的字符,例如将 "\n" 转换为换行符。 - jlordo
请查看Apache文档:https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/StringEscapeUtils.html - ΦXocę 웃 Пepeúpa ツ
显示剩余2条评论
8个回答

62

尝试

str = org.apache.commons.lang3.StringEscapeUtils.unescapeJava(str);

来自Apache Commons Lang


2
如果Java本身提供了解析值的功能,那么为什么我们要使用任何第三方工具呢? - Bhavik Ambani
2
@BhavikAmbani,请解释一下如何做到,因为你的答案明显没有说明白。 - SirDarius
1
@BhavikAmbani 不对,当他打印出他的字符串时,他看到的是 Dodd\u2013Frank,而当我们打印出你的字符串时,我们看到的是 Dodd-Frank。(在任何转换之前),他的字符串是 "Dodd\\u2013Frank",你的字符串是 "Dodd\u2013Frank" - jlordo
3
这可能会在简单情况下解决您的问题,但要小心。如果您尝试在JSON编码的字符串上使用此解决方案,并且其中包含您想要取消转义的UTF8字符,则会取消转义您不想要处理的内容:例如,如果此字符串位于JSON片段中"\u003ca href="http://twitter.com" rel="nofollow"\u003eTwitter Web Client\u003c/a\u003e" - Justin Standard
str = org.apache.commons.text.StringEscapeUtils.unescapeJava(str);因为commons.lang3已经被弃用。 - user8091544
显示剩余3条评论

17

java.util.Properties

您可以利用 java.util.Properties 支持带有 '\uXXXX' 转义序列的字符串的特性来执行以下操作:

Properties p = new Properties();
p.load(new StringReader("key="+yourInputString));
System.out.println("Escaped value: " + p.getProperty("key"));

不太优雅,但是功能上可行。

为了处理可能发生的 IOExeception,你可能需要使用 try-catch。

Properties p = new Properties();
try { p.load( new StringReader( "key=" + input ) ) ; } catch ( IOException e ) { e.printStackTrace(); }
System.out.println( "Escaped value: " + p.getProperty( "key" ) );

不会处理换行符。 - Łukasz
如所述,这是正确的,尽管此解决方案仅适用于一次处理一行。 - drobert
是的,我只是在警告人们,因为我遇到了这个问题。实际上,我用一些特殊的字符串替换了换行符,进行了转换并再次转换回来,效果很好,但对于生产代码来说并不完美。 - Łukasz
可以实现。另一种方法是使用 BufferedReaderBufferedInputSteam 逐行读入并将此算法应用于每一行。 - drobert

2

尝试

str = org.apache.commons.text.StringEscapeUtils.unescapeJava(str);

因为org.apache.commons.lang3.StringEscapeUtils已被弃用。


0
假设您有一个Unicode值,例如00B0(度符号或上标“o”,如西班牙语中“primero”的缩写)
这里有一个函数可以实现您想要的功能:
public static String  unicodeToString( char  charValue )
{
    Character   ch = new Character( charValue );

    return ch.toString();
}

0

我使用了StringEscapeUtils.unescapeXml来对从返回XML结果的API加载的字符串进行反转义。


0

org.apache.commons:commons-text 中的 UnicodeUnescaper 也是可以接受的。

new UnicodeUnescaper().translate("Dodd\u2013Frank")


UnicodeUnescaper().translate(...)需要一个writer,可能是一个StringWriter - 你可以直接使用commons-text中的import org.apache.commons.text.StringEscapeUtils.unescapeJava - Chris Wolf

-2

也许以下解决方案可以在不需要任何额外依赖的情况下正确解码字符串。

这个解决方案在 Scala REPL 中可以工作,但在仅使用 Java 的解决方案中也应该同样有效。

import java.nio.charset.StandardCharsets
import java.nio.charset.Charset

> StandardCharsets.UTF_8.decode(Charset.forName("UTF-8").encode("Dodd\u2013Frank"))
res: java.nio.CharBuffer = Dodd–Frank

1
尝试过这个,但实际上解码UTF-8字符的是它直接在字符串中给出的事实。你的例子所做的是取一个UTF-8字符串,对其进行编码、解码,而幸运的是,我们得到了与输入相同的输出。 - Florian Heer
好奇,对于这个解决方案,什么样的字符串示例会无法转换? - cevaris
2
在源代码中,"\u2013" 已经被转换为 UTF-8 字符。正确的表示问题的方式是将文本转换为 "\u2013",因为它包含反斜杠和每个字符。 - Florian Heer

-3
你可以像这样将字节缓冲区转换为字符串:
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.ByteBuffer

public static CharsetDecoder decoder = CharsetDecoder.newDecoder();

public static String byteBufferToString(ByteBuffer buffer)
{
    String data = "";
    try 
    {
        // EDITOR'S NOTE -- There is no 'position' method for ByteBuffer.
        //                   As such, this is pseudocode.
        int old_position = buffer.position();
        data = decoder.decode(buffer).toString();
        // reset buffer's position to its original so it is not altered:
        buffer.position(old_position);  
    }
    catch (Exception e)
    {
        e.printStackTrace();
        return "";
    }
    return data;
 }

解码器是Java.nio包中CharsetDecoder类的对象。很抱歉更新了回答。感谢您提醒我。:) - Abhishek_Mishra

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