我有一个Unicode编码字符串\uXXXX
,我希望将其转换为常规字母(UTF-8)。例如:
String myString = "\u0048\u0065\u006C\u006C\u006F World";
应该成为
"Hello World"
我知道当我打印字符串时会显示Hello world
。我的问题是我从Unix机器上的文件中读取文件名,然后我搜索它们。文件名使用Unicode编码,当我搜索文件时,我找不到它们,因为它搜索名称中包含\uXXXX
的文件。
答案 0 :(得分:73)
Apache Commons Lang StringEscapeUtils.unescapeJava()可以正确解码。
import org.apache.commons.lang.StringEscapeUtils;
@Test
public void testUnescapeJava() {
String sJava="\\u0048\\u0065\\u006C\\u006C\\u006F";
System.out.println("StringEscapeUtils.unescapeJava(sJava):\n" + StringEscapeUtils.unescapeJava(sJava));
}
output:
StringEscapeUtils.unescapeJava(sJava):
Hello
答案 1 :(得分:38)
技术上:
String myString = "\u0048\u0065\u006C\u006C\u006F World";
自动将其转换为"Hello World"
,因此我假设您正在读取某个文件中的字符串。为了将其转换为“Hello”,您必须将文本解析为单独的unicode数字(取\uXXXX
并获取XXXX
)然后执行Integer.ParseInt(XXXX, 16)
以获得十六进制值,然后到char
获取实际字符的情况。
编辑:完成此操作的一些代码:
String str = myString.split(" ")[0];
str = str.replace("\\","");
String[] arr = str.split("u");
String text = "";
for(int i = 1; i < arr.length; i++){
int hexVal = Integer.parseInt(arr[i], 16);
text += (char)hexVal;
}
// Text will now have Hello
答案 2 :(得分:22)
您可以使用Apache Commons Lang中的StringEscapeUtils
,即:
String Title = StringEscapeUtils.unescapeJava("\u0048\u0065\u006C\u006C\u006F");
答案 3 :(得分:15)
在java中用于转换字符串(String)中的字节流(byte [])并返回String类具有以下特性:
构造函数PreparedStatement stmts = connection.prepareStatement("INSERT INTO detil_bet (id_user, id_room, id_bet, bettype) VALUES (?, ?, ?, ? ");
接收带有编码的输入字节流;如果省略编码,默认情况下将接受
String (byte [] bytes, String enc)
返回以指定编码记录的字节流;编码也可以省略。
getBytes Method (String enc)
<强>更新强>
由于Java 1.7使用try {
String myString = "\u0048\u0065\u006C\u006C\u006F World";
byte[] utf8Bytes = myString.getBytes("UTF8");
String text = new String(utf8Bytes,"UTF8");
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
:
StandardCharsets.UTF_8
答案 4 :(得分:7)
这种简单的方法适用于大多数情况,但会绊倒像&#34; u005Cu005C&#34;哪个应解码为字符串&#34; \ u0048&#34;但实际上会解码&#34; H&#34;作为第一关产生&#34; \ u0048&#34;作为工作字符串,然后由while循环再次处理。
static final String decode(final String in)
{
String working = in;
int index;
index = working.indexOf("\\u");
while(index > -1)
{
int length = working.length();
if(index > (length-6))break;
int numStart = index + 2;
int numFinish = numStart + 4;
String substring = working.substring(numStart, numFinish);
int number = Integer.parseInt(substring,16);
String stringStart = working.substring(0, index);
String stringEnd = working.substring(numFinish);
working = stringStart + ((char)number) + stringEnd;
index = working.indexOf("\\u");
}
return working;
}
答案 5 :(得分:4)
你的问题并不完全清楚,但我假设你说你有一个文件,其中该文件的每一行都是文件名。每个文件名都是这样的:
\u0048\u0065\u006C\u006C\u006F
换句话说,文件名文件中的字符为\
,u
,0
,0
,4
,8
等等。
如果是这样,你所看到的是预期的。 Java仅在源代码中的字符串文字中翻译\uXXXX
序列(以及在读取存储的Properties
个对象时)。当您阅读您提交的内容时,您将拥有一个由字符\
,u
,0
,0
,4
,{{1}组成的字符串}等等,不字符串8
。
因此,您需要解析该字符串以提取Hello
,0048
等片段,然后将它们转换为0065
并从char
创建一个字符串然后将该字符串传递给打开文件的例程。
答案 6 :(得分:3)
试
private static final Charset UTF_8 = Charset.forName("UTF-8");
private String forceUtf8Coding(String input) {return new String(input.getBytes(UTF_8), UTF_8))}
答案 7 :(得分:3)
更短的版本:
public static String unescapeJava(String escaped) {
if(escaped.indexOf("\\u")==-1)
return escaped;
String processed="";
int position=escaped.indexOf("\\u");
while(position!=-1) {
if(position!=0)
processed+=escaped.substring(0,position);
String token=escaped.substring(position+2,position+6);
escaped=escaped.substring(position+6);
processed+=(char)Integer.parseInt(token,16);
position=escaped.indexOf("\\u");
}
processed+=escaped;
return processed;
}
答案 8 :(得分:2)
StringEscapeUtils为deprecated。
因此,您可以改用他们新的commons-text库:
compile 'org.apache.commons:commons-text:1.8'
OR
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.8</version>
</dependency>
示例代码:
org.apache.commons.text.StringEscapeUtils.unescapeJava(escapedString);
答案 9 :(得分:1)
我知道使用JsonObject的一种简单方法:
try {
JSONObject json = new JSONObject();
json.put("string", myString);
String converted = json.getString("string");
} catch (JSONException e) {
e.printStackTrace();
}
答案 10 :(得分:0)
AbstractConfigurableMongoDbMessageStore
的 UnicodeUnescaper
也可以接受。
org.apache.commons:commons-text
返回new UnicodeUnescaper().translate("\u0048\u0065\u006C\u006C\u006F World")
答案 11 :(得分:0)
@NominSim 可能还有其他字符,所以我应该按长度检测。
private String forceUtf8Coding(String str) {
str = str.replace("\\","");
String[] arr = str.split("u");
StringBuilder text = new StringBuilder();
for(int i = 1; i < arr.length; i++){
String a = arr[i];
String b = "";
if (arr[i].length() > 4){
a = arr[i].substring(0, 4);
b = arr[i].substring(4);
}
int hexVal = Integer.parseInt(a, 16);
text.append((char) hexVal).append(b);
}
return text.toString();
}
答案 12 :(得分:0)
对于Java 9+,您可以使用replaceAll类的新Matcher方法。
private static final Pattern UNICODE_PATTERN = Pattern.compile("\\\\u([0-9A-Fa-f]{4})");
public static String unescapeUnicode(String unescaped) {
return UNICODE_PATTERN.matcher(unescaped).replaceAll(r -> String.valueOf((char) Integer.parseInt(r.group(1), 16)));
}
public static void main(String[] args) {
String originalMessage = "\\u0048\\u0065\\u006C\\u006C\\u006F World";
String unescapedMessage = unescapeUnicode(originalMessage);
System.out.println(unescapedMessage);
}
我相信这种方法比unescapeJava的StringEscapeUtils的主要优势(除了不使用额外的库)是,您只能转换unicode字符(如果愿意),因为后者可以转换所有转义的Java字符(例如\ n或\ t)。如果您希望转换所有转义的字符,则库实际上是最佳选择。
答案 13 :(得分:0)
快速
fun unicodeDecode(unicode: String): String {
val stringBuffer = StringBuilder()
var i = 0
while (i < unicode.length) {
if (i + 1 < unicode.length)
if (unicode[i].toString() + unicode[i + 1].toString() == "\\u") {
val symbol = unicode.substring(i + 2, i + 6)
val c = Integer.parseInt(symbol, 16)
stringBuffer.append(c.toChar())
i += 5
} else stringBuffer.append(unicode[i])
i++
}
return stringBuffer.toString()
}
答案 14 :(得分:0)
只想使用正则表达式贡献我的版本:
private static final String UNICODE_REGEX = "\\\\u([0-9a-f]{4})";
private static final Pattern UNICODE_PATTERN = Pattern.compile(UNICODE_REGEX);
...
String message = "\u0048\u0065\u006C\u006C\u006F World";
Matcher matcher = UNICODE_PATTERN.matcher(message);
StringBuffer decodedMessage = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(
decodedMessage, String.valueOf((char) Integer.parseInt(matcher.group(1), 16)));
}
matcher.appendTail(decodedMessage);
System.out.println(decodedMessage.toString());
答案 15 :(得分:0)
还有两种实现方法
<input [(ngModel)] = "txtAddNewItemType" type="text" class="form-
control" id="txtAddNewItemType">
答案 16 :(得分:0)
我写了一个高性能的防错解决方案:
public static final String decode(final String in) {
int p1 = in.indexOf("\\u");
if (p1 < 0)
return in;
StringBuilder sb = new StringBuilder();
while (true) {
int p2 = p1 + 6;
if (p2 > in.length()) {
sb.append(in.subSequence(p1, in.length()));
break;
}
try {
int c = Integer.parseInt(in.substring(p1 + 2, p1 + 6), 16);
sb.append((char) c);
p1 += 6;
} catch (Exception e) {
sb.append(in.subSequence(p1, p1 + 2));
p1 += 2;
}
int p0 = in.indexOf("\\u", p1);
if (p0 < 0) {
sb.append(in.subSequence(p1, in.length()));
break;
} else {
sb.append(in.subSequence(p1, p0));
p1 = p0;
}
}
return sb.toString();
}
答案 17 :(得分:0)
我发现许多答案都没有解决“补充字符”的问题。这是支持它的正确方法。没有第三方库,纯Java实现。
http://www.oracle.com/us/technologies/java/supplementary-142654.html
public static String fromUnicode(String unicode) {
String str = unicode.replace("\\", "");
String[] arr = str.split("u");
StringBuffer text = new StringBuffer();
for (int i = 1; i < arr.length; i++) {
int hexVal = Integer.parseInt(arr[i], 16);
text.append(Character.toChars(hexVal));
}
return text.toString();
}
public static String toUnicode(String text) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < text.length(); i++) {
int codePoint = text.codePointAt(i);
// Skip over the second char in a surrogate pair
if (codePoint > 0xffff) {
i++;
}
String hex = Integer.toHexString(codePoint);
sb.append("\\u");
for (int j = 0; j < 4 - hex.length(); j++) {
sb.append("0");
}
sb.append(hex);
}
return sb.toString();
}
@Test
public void toUnicode() {
System.out.println(toUnicode(""));
System.out.println(toUnicode(""));
System.out.println(toUnicode("Hello World"));
}
// output:
// \u1f60a
// \u1f970
// \u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064
@Test
public void fromUnicode() {
System.out.println(fromUnicode("\\u1f60a"));
System.out.println(fromUnicode("\\u1f970"));
System.out.println(fromUnicode("\\u0048\\u0065\\u006c\\u006c\\u006f\\u0020\\u0057\\u006f\\u0072\\u006c\\u0064"));
}
// output:
//
//
// Hello World
答案 18 :(得分:0)
有关使用The Apache Commons Lang's的答案的更新, StringEscapeUtils.unescapeJava()已弃用,替换为 Apache Commons Text 的StringEscapeUtils.unescapeJava()
答案 19 :(得分:0)
另一种实现此目的的方法可以是利用Java 9引入的chars()
,它可以用于遍历字符,以确保传递映射到surrogate code point的任何字符未解释。可以用作:-
String myString = "\u0048\u0065\u006C\u006C\u006F World";
myString.chars().forEach(a -> System.out.print((char)a));
// would print "Hello World"
答案 20 :(得分:0)
Kotlin解决方案:
val result = String(someText.toByteArray())
Kotlin在任何地方使用UTF-8作为默认编码
您也可以将其实现为String类的扩展名:
fun String.unescape(): String {
return String(this.toByteArray())
}
然后简单地使用它:
val result = someText.unescape()
)
答案 21 :(得分:0)
这是我的解决方案......
String decodedName = JwtJson.substring(startOfName, endOfName);
StringBuilder builtName = new StringBuilder();
int i = 0;
while ( i < decodedName.length() )
{
if ( decodedName.substring(i).startsWith("\\u"))
{
i=i+2;
builtName.append(Character.toChars(Integer.parseInt(decodedName.substring(i,i+4), 16)));
i=i+4;
}
else
{
builtName.append(decodedName.charAt(i));
i = i+1;
}
};
答案 22 :(得分:0)
实际上,我写了一个包含一些实用程序的开源库。其中之一是将Unicode序列转换为String,反之亦然。我发现它非常有用。以下是关于这个有关Unicode转换器的库的文章的引用:
类StringUnicodeEncoderDecoder具有可以转换的方法 字符串(以任何语言)转换为Unicode字符序列和 反之亦然。例如String&#34; Hello World&#34;将被转换为
&#34; \ u0065 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006 \ u006&#34>
可以恢复。
以下是整篇文章的链接,它解释了图书馆的实用工具以及如何让图书馆使用它。它可以作为Maven工件或Github的源代码提供。这是非常容易使用。 Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison