Создание символа Unicode из его номера


114

Я хочу отобразить символ Unicode в Java. Если я сделаю это, все будет нормально:

String symbol = "\u2202";

символ равен «∂». Это то, что я хочу.

Проблема в том, что я знаю номер Unicode, и мне нужно создать из него символ Unicode. Я попробовал (для меня) очевидное:

int c = 2202;
String symbol =  "\\u" + c;

Однако в этом случае символ равен «\ u2202». Я не этого хочу.

Как я могу создать символ, если я знаю его номер в Юникоде (но только во время выполнения - я не могу жестко запрограммировать его, как в первом примере)?


1
Удалите первую обратную косую черту, чтобы вместо экранирования обратной косой черты она экранировала последовательность Unicode. Использование «\\» сообщает Java, что вы хотите распечатать «\», а не использовать его в качестве прошлого escape-последовательности для символов Unicode. Если вы удалите первую, она будет экранировать последовательность Unicode, а не второй обратный слеш. По крайней мере, насколько мне известно, будет.
Иск Фонда Моники

Ответы:


73

Просто переведите ваш файл intв файл char. Вы можете преобразовать это в Stringиспользование Character.toString():

String s = Character.toString((char)c);

РЕДАКТИРОВАТЬ:

Просто помните, что escape-последовательности в исходном коде Java ( \uбиты) находятся в HEX, поэтому, если вы пытаетесь воспроизвести escape-последовательность, вам понадобится что-то вроде int c = 0x2202.


3
Это просто квадратная коробка, ࢚. Это не дает мне «∂».
Пол Райнерс

19
Опасно, Уилл Робинсон! Не забывайте, что кодовые точки Unicode не обязательно помещаются в char . Поэтому вам нужно быть абсолютно уверенным заранее, что ваше значение cменьше 0x10000, иначе этот подход ужасно сломается.
Дэвид Гивен

1
@NickHartley Извините, не слушайте --- вы неправильно прочитали 0x10000 на 10000?
Дэвид Гивен

10
Вот почему я сказал «ниже»! И я должен подчеркнуть, что, несмотря на то, что символы Java увеличиваются только до 0xffff, кодовые точки Unicode достигают 0xfffff. Стандарт Unicode был изменен после разработки Java. В наши дни символы Java технически содержат слова UTF-16, а не кодовые точки Unicode, и если вы забудете об этом, это приведет к ужасной поломке, когда ваше приложение встретит экзотический скрипт.
Дэвид Гивен

3
@DavidGiven спасибо за Java chars go up to 0xFFFF. Я не знал этого.
Тони Эннис

128

Если вы хотите получить кодированный блок кода UTF-16 как a char, вы можете проанализировать целое число и привести к нему, как предлагали другие.

Если вы хотите поддерживать все кодовые точки, используйте Character.toChars(int). Это будет обрабатывать случаи, когда кодовые точки не могут поместиться в одно charзначение.

Док говорит:

Преобразует указанный символ (кодовая точка Unicode) в его представление UTF-16, хранящееся в массиве символов. Если указанная кодовая точка является значением BMP (Basic Multilingual Plane или Plane 0), результирующий массив символов имеет то же значение, что и codePoint. Если указанная кодовая точка является дополнительной кодовой точкой, результирующий массив символов имеет соответствующую суррогатную пару.


Хотя это более общее решение, и во многих случаях вы должны использовать его вместо принятого ответа, принятый ответ ближе к конкретной проблеме, которую просил Пол.
Jochem Kuijpers

2
Во-первых, спасибо! В Scala я по-прежнему не могу анализировать символы размером больше char. scala> "👨‍🎨".map(_.toInt).flatMap((i: Int) => Character.toChars(i)).map(_.toHexString)дает res11: scala.collection.immutable.IndexedSeq[String] = Vector(f468, 200d, f3a8) этот смайлик, «мужской певец», адресованный с тремя точками кода U+1f468, U+200dи U+1f3a8. Старшая цифра отсутствует. Я могу добавить его с помощью побитового ИЛИ ( stackoverflow.com/a/2220476/1007926 ), но не знаю, как определить, какие проанализированные символы были усечены. Спасибо!
Питер Бечич

1
@JochemKuijpers Я не согласен с тем, что «принятый ответ ближе к конкретной проблеме» . ОП явно спросил: «Как я могу построить символ, если я знаю его номер в Юникоде ...?» , и принятый ответ не может работать, если этот «номер Unicode» находится за пределами BMP. Например, принятый ответ не подходит для действительной кодовой точки 0x1040C, потому что он находится в SMP. Это плохой ответ, и его следует исправить или удалить.
скомиса

Сценарий @skomisa OPs ограничен представлением шестнадцатеричной escape-последовательности Unicode. Если у вас есть символ, который должен быть закодирован как суррогатная пара, это отражается в этих escape-последовательностях, поэтому в конечном итоге он все равно работает. Как я уже сказал, это более общее решение, и вы должны его использовать.
Jochem

20

Другие ответы здесь либо поддерживают только Unicode до U + FFFF (ответы, касающиеся только одного экземпляра char), либо не говорят, как добраться до фактического символа (ответы останавливаются на Character.toChars () или с использованием неправильного метода после этого), так что добавляю и свой ответ здесь.

Вот что необходимо сделать для поддержки дополнительных кодовых точек:

// this character:
// http://www.isthisthingon.org/unicode/index.php?page=1F&subpage=4&glyph=1F495
// using code points here, not U+n notation
// for equivalence with U+n, below would be 0xnnnn
int codePoint = 128149;
// converting to char[] pair
char[] charPair = Character.toChars(codePoint);
// and to String, containing the character we want
String symbol = new String(charPair);

// we now have str with the desired character as the first item
// confirm that we indeed have character with code point 128149
System.out.println("First code point: " + symbol.codePointAt(0));

Я также быстро проверил, какие методы преобразования работают, а какие нет.

int codePoint = 128149;
char[] charPair = Character.toChars(codePoint);

String str = new String(charPair, 0, 2);
System.out.println("First code point: " + str.codePointAt(0));    // 128149, worked
String str2 = charPair.toString();
System.out.println("Second code point: " + str2.codePointAt(0));  // 91, didn't work
String str3 = new String(charPair);
System.out.println("Third code point: " + str3.codePointAt(0));   // 128149, worked
String str4 = String.valueOf(codePoint);
System.out.println("Fourth code point: " + str4.codePointAt(0));  // 49, didn't work
String str5 = new String(new int[] {codePoint}, 0, 1);
System.out.println("Fifth code point: " + str5.codePointAt(0));   // 128149, worked

Почему это не работает как однострочный? new String(Character.toChars(121849));не работает в консоли Eclipse, но трехстрочная версия работает.
Noumenon

@Noumenon не может воспроизвести проблему, работает одинаково хорошо для меня
eis

Престижность за продвижение. Для str4задания не должно codeбыть codePointвместо этого?
skomisa

6

Помните, что charэто целочисленный тип, поэтому ему можно присвоить целочисленное значение, а также константу типа char.

char c = 0x2202;//aka 8706 in decimal. \u codepoints are in hex.
String s = String.valueOf(c);

Это просто квадратная коробка, ࢚. Это не дает мне «∂».
Пол Райнерс,

3
Это потому, что 2202 - это не то, что intвы искали. Вы искали 0x2202. Моя вина. В любом случае, если у вас есть intкод, который вы ищете, вы можете просто преобразовать его в a charи использовать (для создания a, Stringесли хотите).
ILMTitan

6

Этот сработал для меня.

  String cc2 = "2202";
  String text2 = String.valueOf(Character.toChars(Integer.parseInt(cc2, 16)));

Теперь text2 будет иметь ∂.


4
String st="2202";
int cp=Integer.parseInt(st,16);// it convert st into hex number.
char c[]=Character.toChars(cp);
System.out.println(c);// its display the character corresponding to '\u2202'.

1
Хотя этот пост может ответить на вопрос, требуется объяснение того, что вы делаете; для повышения качества и удобочитаемости вашего ответа
Аджил О.

1
Спасибо, мне очень помогло! Работает нормально и проще, чем другие решения здесь (действительно, Java-люди очень любят все усложнять).
парсер

2

Вот как вы это делаете:

int cc = 0x2202;
char ccc = (char) Integer.parseInt(String.valueOf(cc), 16);
final String text = String.valueOf(ccc);

Это решение принадлежит Арне Вайхёю.


Вы говорите, что это работает? Если да, то это работает, потому что вы интерпретируете две тысячи двести два как 0x2202, что, конечно, совсем не одно и то же.
dty 07

4
О нет, подожди! Значения Unicode (escape-последовательности \ u в исходном коде Java) являются шестнадцатеричными! Так что это правильно. Вы просто всех ввели в заблуждение, говоря int c = 2202, что это неправильно! Лучшее решение, чем это, - просто сказать, int c = 0x2202что избавит вас от использования String и т. Д.
dty

3
+1 @dty: Нет абсолютно никакого вызова средней char ccc...линии. Просто используйте, int cc = 0x2202;а потомfinal String text=String.valueOf(cc);
Эндрю Кунс

2

Хотя это старый вопрос, в Java 11, выпущенной сегодня, есть очень простой способ сделать это: вы можете использовать новую перегрузку Character.toString () :

public static String toString​(int codePoint)

Returns a String object representing the specified character (Unicode code point). The result is a string of length 1 or 2, consisting solely of the specified codePoint.

Parameters:
codePoint - the codePoint to be converted

Returns:
the string representation of the specified codePoint

Throws:
IllegalArgumentException - if the specified codePoint is not a valid Unicode code point.

Since:
11

Поскольку этот метод поддерживает любую кодовую точку Unicode, длина возвращаемой строки не обязательно равна 1.

Код, необходимый для примера, приведенного в вопросе, прост:

    int codePoint = '\u2202';
    String s = Character.toString(codePoint); // <<< Requires JDK 11 !!!
    System.out.println(s); // Prints ∂

Такой подход дает несколько преимуществ:

  • Он работает для любой кодовой точки Unicode, а не только для тех, которые можно обрабатывать с помощью char.
  • Он краток, и его легко понять, что делает код.
  • Он возвращает значение в виде строки, а не в виде char[], что часто бывает у вас. Ответ, опубликованный Макдауэллом , подходит, если вы хотите, чтобы код возвращался как char[].

Некоторые дополнительные пояснения по этому поводу, поскольку этот ответ сразу же заставил меня понять, как создать переменную codePoint. Синтаксис здесь должен быть следующим: int codePoint = 0x2202;То: String s = Character.toString(codePoint); // <<< Requires JDK 11 !!! Или однострочным: System.out.println(Character.toString(0x2202)); // Prints ∂ Надеюсь, это поможет кому-то другому, использующему эту функцию JDK 11.
Лоатиан,

1

В приведенном ниже коде будут записаны 4 символа Юникода (представленные десятичными знаками) для слова «быть» на японском языке. Да, в глаголе «быть» в японском языке 4 символа! Значение символов находится в десятичном формате, и оно было считано в массив String [] - например, с помощью split. Если у вас есть Octal или Hex, parseInt также принимает основание.

// pseudo code
// 1. init the String[] containing the 4 unicodes in decima :: intsInStrs 
// 2. allocate the proper number of character pairs :: c2s
// 3. Using Integer.parseInt (... with radix or not) get the right int value
// 4. place it in the correct location of in the array of character pairs
// 5. convert c2s[] to String
// 6. print 

String[] intsInStrs = {"12354", "12426", "12414", "12377"}; // 1.
char [] c2s = new char [intsInStrs.length * 2];  // 2.  two chars per unicode

int ii = 0;
for (String intString : intsInStrs) {
    // 3. NB ii*2 because the 16 bit value of Unicode is written in 2 chars
    Character.toChars(Integer.parseInt(intsInStrs[ii]), c2s, ii * 2 ); // 3 + 4
    ++ii; // advance to the next char
}

String symbols = new String(c2s);  // 5.
System.out.println("\nLooooonger code point: " + symbols); // 6.
// I tested it in Eclipse and Java 7 and it works.  Enjoy

1

Вот блок для распечатки Юникода символов между \u00c0к \u00ff:

char[] ca = {'\u00c0'};
for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 16; j++) {
        String sc = new String(ca);
        System.out.print(sc + " ");
        ca[0]++;
    }
    System.out.println();
}

0

К сожалению, удаление одного люфта, упомянутого в первом комментарии (newbiedoodle), не приводит к хорошему результату. Большинство (если не все) IDE выдают синтаксические ошибки. Причина в том, что формат Java Escaped Unicode ожидает синтаксиса «\ uXXXX», где XXXX - это 4 шестнадцатеричные цифры, которые являются обязательными. Попытки сложить эту веревку из кусков не удались. Конечно, «\ u» - это не то же самое, что «\\ u». Первый синтаксис означает экранированную «u», второй означает экранированный люфт (который является люфтом) с последующим «u». Странно, что на страницах Apache представлена ​​утилита, делающая именно это поведение. Но на самом деле это утилита Escape mimic . У Apache есть несколько собственных утилит (я их не тестировал), которые делают эту работу за вас. Может быть, это еще не то, что вы хотите иметь.Но эта утилита 1 имеет хороший подход к решению. С комбинацией, описанной выше (MeraNaamJoker). Мое решение - создать эту экранированную мимическую строку, а затем преобразовать ее обратно в Unicode (чтобы избежать реального ограничения Escaped Unicode). Я использовал его для копирования текста, поэтому возможно, что в методе uencode будет лучше использовать '\\ u', кроме '\\\\ u'. Попытайся.

  /**
   * Converts character to the mimic unicode format i.e. '\\u0020'.
   * 
   * This format is the Java source code format.
   * 
   *   CharUtils.unicodeEscaped(' ') = "\\u0020"
   *   CharUtils.unicodeEscaped('A') = "\\u0041"
   * 
   * @param ch  the character to convert
   * @return is in the mimic of escaped unicode string, 
   */
  public static String unicodeEscaped(char ch) {
    String returnStr;
    //String uniTemplate = "\u0000";
    final static String charEsc = "\\u";

    if (ch < 0x10) {
      returnStr = "000" + Integer.toHexString(ch);
    }
    else if (ch < 0x100) {
      returnStr = "00" + Integer.toHexString(ch);
    }
    else if (ch < 0x1000) {
      returnStr = "0" + Integer.toHexString(ch);
    }
    else
      returnStr = "" + Integer.toHexString(ch);

    return charEsc + returnStr;
  }

  /**
   * Converts the string from UTF8 to mimic unicode format i.e. '\\u0020'.
   * notice: i cannot use real unicode format, because this is immediately translated
   * to the character in time of compiling and editor (i.e. netbeans) checking it
   * instead reaal unicode format i.e. '\u0020' i using mimic unicode format '\\u0020'
   * as a string, but it doesn't gives the same results, of course
   * 
   * This format is the Java source code format.
   * 
   *   CharUtils.unicodeEscaped(' ') = "\\u0020"
   *   CharUtils.unicodeEscaped('A') = "\\u0041"
   * 
   * @param String - nationalString in the UTF8 string to convert
   * @return is the string in JAVA unicode mimic escaped
   */
  public String encodeStr(String nationalString) throws UnsupportedEncodingException {
    String convertedString = "";

    for (int i = 0; i < nationalString.length(); i++) {
      Character chs = nationalString.charAt(i);
      convertedString += unicodeEscaped(chs);
    }
    return convertedString;
  }

  /**
   * Converts the string from mimic unicode format i.e. '\\u0020' back to UTF8.
   * 
   * This format is the Java source code format.
   * 
   *   CharUtils.unicodeEscaped(' ') = "\\u0020"
   *   CharUtils.unicodeEscaped('A') = "\\u0041"
   * 
   * @param String - nationalString in the JAVA unicode mimic escaped
   * @return is the string in UTF8 string
   */
  public String uencodeStr(String escapedString) throws UnsupportedEncodingException {
    String convertedString = "";

    String[] arrStr = escapedString.split("\\\\u");
    String str, istr;
    for (int i = 1; i < arrStr.length; i++) {
      str = arrStr[i];
      if (!str.isEmpty()) {
        Integer iI = Integer.parseInt(str, 16);
        char[] chaCha = Character.toChars(iI);
        convertedString += String.valueOf(chaCha);
      }
    }
    return convertedString;
  }


-7

(ОТВЕТ В DOT NET 4.5 и в java должен существовать аналогичный подход)

Я из Западной Бенгалии в ИНДИИ. Как я понимаю , ваша проблема ... Вы хотите производить похожие на «অ» (Это письмо на бенгальском языке) , который имеет Unicode HEX: 0X0985.

Теперь, если вы знаете это значение применительно к вашему языку, то как вы правильно создадите этот специфичный для языка символ Unicode?

В Dot Net это очень просто:

int c = 0X0985;
string x = Char.ConvertFromUtf32(c);

Теперь x - ваш ответ. Но это преобразование HEX на HEX, и преобразование предложений в предложения - это работа для исследователей: P


вопрос действительно для java. Я не понимаю, как здесь связан ответ .NET.
eis
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.