Как преобразовать строку с кодировкой Unicode в строку букв
У меня есть строка с Unicode encoding, \uXXXX
, и я хочу преобразовать ее в обычную букву (UTF-8). Например:
String myString = "\u0048\u0065\u006C\u006C\u006F World";
должен стать
"Hello World"
Я знаю, что когда я печатаю строку, она показывает Hello world
. Моя проблема в том, что я читаю имена файлов из файла на компьютере Unix, а затем я их ищу. Имена файлов с кодировкой Юникода, и когда я ищу файлы, я не могу их найти, так как он ищет файл с \uXXXX
в его имени.
Ответы
Ответ 1
Технически:
String myString = "\u0048\u0065\u006C\u006C\u006F World";
автоматически преобразует его в "Hello World"
, поэтому я предполагаю, что вы читаете строку из какого-либо файла. Чтобы преобразовать его в "Привет", вам придется разобрать текст на отдельные цифры в Юникоде (возьмите \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
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
Ответ 3
Вы можете использовать StringEscapeUtils
из Apache Commons Lang, то есть:
String Title = StringEscapeUtils.unescapeJava("\u0048\u0065\u006C\u006C\u006F");
Ответ 4
Байт-кодировки и строки
В java для преобразования байтового потока (byte []) в строке (String) и обратно в класс String есть следующие функции:
String (byte [] bytes, String enc)
конструктора String (byte [] bytes, String enc)
получает входной поток байтов с их кодированием; если кодирование опущено, оно будет принято по умолчанию
getBytes Method (String enc)
возвращает поток байтов, записанный в указанной кодировке; кодирование также может быть опущено.
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();
}
ОБНОВИТЬ:
Поскольку Java 1.7 использует StandardCharsets.UTF_8
:
String utf8Text = "\u0048\u0065\u006C\u006C\u006F World";
byte[] bytes = utf8Text.getBytes(StandardCharsets.UTF_8);
String text = new String(bytes, StandardCharsets.UTF_8);
Ответ 5
Этот простой метод будет работать в большинстве случаев, но будет срабатывать над чем-то вроде "u005Cu005C", который должен декодировать строку "\ u0048", но фактически декодирует "H", поскольку первый проход производит "\ u0048" в качестве рабочая строка, которая затем снова обрабатывается циклом 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;
}
Ответ 6
Это не совсем ясно из вашего вопроса, но я предполагаю, что вы говорите, что у вас есть файл, где каждая строка этого файла является именем файла. И каждое имя файла выглядит примерно так:
\u0048\u0065\u006C\u006C\u006F
Другими словами, символы в файле имен файлов \
, u
, 0
, 0
, 4
, 8
и т.д.
Если да, то то, что вы видите, ожидается. Java только переводит последовательности \uXXXX
в строковых литералах в исходном коде (и при чтении в хранимых объектах Properties
). Когда вы прочтете содержимое, которое у вас есть, у вас будет строка, состоящая из символов \
, u
, 0
, 0
, 4
, 8
и т.д. И не строка Hello
.
Итак, вам нужно проанализировать эту строку, чтобы извлечь фрагменты 0048
, 0065
и т.д., а затем преобразовать их в char
и создать строку из этих char
, а затем передать эту строку в подпрограмму который открывает файл.
Ответ 7
Более короткая версия:
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
попробовать
private static final Charset UTF_8 = Charset.forName("UTF-8");
private String forceUtf8Coding(String input) {return new String(input.getBytes(UTF_8), UTF_8))}
Ответ 9
один простой способ, который я знаю, используя JsonObject:
try {
JSONObject json = new JSONObject();
json.put("string", myString);
String converted = json.getString("string");
} catch (JSONException e) {
e.printStackTrace();
}
Ответ 10
Собственно, я написал библиотеку с открытым исходным кодом, содержащую некоторые утилиты. Один из них - преобразование последовательности Unicode в String и наоборот. Я нахожу это очень полезным. Вот цитата из статьи об этой библиотеке об конвертере Unicode:
Класс StringUnicodeEncoderDecoder имеет методы, которые могут преобразовывать String (на любом языке) в последовательность символов Unicode и наоборот. Например, строка "Hello World" будет преобразована в
"\ u0048\u006c\u006c\u006f\u0057\u006f\u006c\u0064"
и может быть восстановлен обратно.
Вот ссылка на всю статью, в которой объясняется, какие утилиты есть в библиотеке и как получить библиотеку для ее использования. Он доступен как артефакт Maven или как источник от Github. Он очень прост в использовании. Библиотека Java с открытым исходным кодом с фильтрацией трассировки стека, синтаксический анализ строк Unicode-конвертер и сравнение версий
Ответ 11
Вот мое решение...
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;
}
};
Ответ 12
public static String getEnglishText(String textWithUnicode){
String word="";
String newText= textWithUnicode;
int position=newText.indexOf("\\u");
while(position!=-1) {
if(position!=0){
word+=newText.substring(0,position);
}
String token=newText.substring(position+2,position+5);
newText=newText.substring(position+5);
word+=(char)Integer.parseInt(token);
position=newText.indexOf("\\u");}
word+=newText;
return word;
}
Это сработало для меня. Проверьте это!!!
Ответ 13
Решение для Котлина:
val result = String(someText.toByteArray())
Kotlin использует UTF-8 везде как кодирование по умолчанию
Также вы можете реализовать его как расширение для класса String:
fun String.unescape(): String {
return String(this.toByteArray())
}
а затем использовать его просто:
val result = someText.unescape()
;)
Ответ 14
Альтернативным способом выполнения этого может быть использование chars()
введенного с Java 9, это можно использовать для итерации по символам, убедившись, что любой символ, который сопоставляется суррогатной кодовой точке, передается через неинтерпретируемый. Это можно использовать как: -
String myString = "\u0048\u0065\u006C\u006C\u006F World";
myString.chars().forEach(a -> System.out.print((char)a));
// would print "Hello World"
Ответ 15
Обновления относительно ответов, предлагающих использование Apache Commons Lang's, StringEscapeUtils.unescapeJava(), было устаревшим, заменой является Apache Commons Text StringEscapeUtils.unescapeJava()
Ответ 16
Ниже приведена копия ответа на другой вопрос: преобразование международной строки в коды u в java
Существует Java-библиотека с открытым исходным кодом MgntUtils, в которой есть утилита, которая преобразует строки в последовательность Unicode и наоборот:
result = "Hello World";
result = StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence(result);
System.out.println(result);
result = StringUnicodeEncoderDecoder.decodeUnicodeSequenceToString(result);
System.out.println(result);
Выход этого кода:
\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064
Hello World
Библиотеку можно найти в Maven Central или в Github. Она поставляется в виде артефакта Maven, с источниками и javadoc.
Вот javadoc для класса StringUnicodeEncoderDecoder
Ответ 17
Я написал качественное и защищенное от ошибок решение:
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();
}
Ответ 18
StringEscapeUtils из библиотеки org.apache.commons.lang3 устарело с версии 3.6.
Таким образом, вместо этого вы можете использовать их новую библиотеку:
compile 'org.apache.commons:commons-text:1.7'
OR
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.7</version>
</dependency>
Пример кода:
org.apache.commons.text.StringEscapeUtils.unescapeJava(escapedString);
Ответ 19
Еще два способа сделать это будут
//This is what StringBuilder internally does on calling toString() Method
char[] charArray = "\u0048\u0065\u006C\u006C\u006F World".toCharArray();
String output = new String(charArray, 0, charArray.length);
//To do it in single line
String output = new StringBuilder("\u0048\u0065\u006C\u006C\u006F World").toString();
Ответ 20
Просто хотел добавить мою версию, используя регулярное выражение:
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());
Ответ 21
Я обнаружил, что многие из ответов не касались вопроса "Дополнительные символы". Вот правильный способ поддержать это. Никаких сторонних библиотек, чистая реализация 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