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

问题描述 投票:0回答:9

我在 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)。请原谅我。

java unicode utf-8 utf8-decode
9个回答
63
投票

尝试

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

来自 Apache Commons Lang


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"));

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
投票

UnicodeUnescaper
来自
org.apache.commons:commons-text
也可以接受。

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


0
投票

如果您无法向项目添加依赖项,或者您根本不想这样做,这里有一个使用正则表达式的相对简单的实现。

import java.util.regex.Pattern;

public final class UnicodeUnescape {

  private static final Pattern PATTERN = Pattern.compile("\\\\u(\\p{XDigit}{4})");

  public static String unescape(String input) {
    return PATTERN
        .matcher(input)
        .replaceAll(
            match -> {
              char c = (char) Integer.parseInt(match.group(1), 16);
              return Character.toString(c);
            });
  }
}

虽然这显然不是最有效的实现。此外,这将处理Unicode转义序列,与

StringEscapeUtils#escapeJava(String)
来自Apache Commons Text不同。

请注意,Java 9 中添加了

Matcher#replaceAll(Function<MatchResult, String>)


这是一个非常基本的、非详尽的单元测试。

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.params.provider.Arguments.arguments;

import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class UnicodeUnescapeTests {

  @ParameterizedTest(name = "\"{0}\" → \"{1}\"")
  @MethodSource
  void testUnescape(String input, String expected) {
    var actual = UnicodeUnescape.unescape(input);
    assertEquals(expected, actual);
  }

  static List<Arguments> testUnescape() {
    return List.of(
        // test input from question
        arguments("Dodd\\u2013Frank", "Dodd–Frank"),
        // test surrogate pair
        arguments("Dodd Frank \\uD83C\\uDF09", "Dodd Frank 🌉"));
  }
}

输出(来自 Gradle):

UnicodeUnescapeTests > ... > "Dodd\u2013Frank" → "Dodd–Frank" PASSED
UnicodeUnescapeTests > ... > "Dodd Frank \uD83C\uDF09" → "Dodd Frank 🌉" PASSED

-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;
 }

-3
投票

也许以下解决方案可以正确解码字符串,而无需任何额外的依赖项。

这在 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
© www.soinside.com 2019 - 2024. All rights reserved.