Подтвердить что ты не робот

Как преобразовать строку с кодировкой Unicode в строку букв

У меня есть строка с Unicode encoding, \uXXXX, и я хочу преобразовать ее в обычную букву (UTF-8). Например:

String myString = "\u0048\u0065\u006C\u006C\u006F World";

должен стать

"Hello World"

Я знаю, что когда я печатаю строку, она показывает Hello world. Моя проблема в том, что я читаю имена файлов из файла на компьютере Unix, а затем я их ищу. Имена файлов с кодировкой Юникода, и когда я ищу файлы, я не могу их найти, так как он ищет файл с \uXXXX в его имени.

4b9b3361

Ответ 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"

Ответ 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