Создание символа 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.

DTY
источник
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);
ILMTitan
источник
Это просто квадратная коробка, ࢚. Это не дает мне «∂».
Пол Райнерс,
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 будет иметь ∂.

MeraNaamJoker
источник
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[].
skomisa
источник
Некоторые дополнительные пояснения по этому поводу, поскольку этот ответ сразу же заставил меня понять, как создать переменную 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
user96265
источник
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();
}
fjiang_ca
источник
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;
  }
Харипрасад
источник
-1

символ c = (символ) 0x2202; Строка s = "" + c;

dave110022
источник
-7

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

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

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

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

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

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

Suman Kr. Нат
источник
вопрос действительно для java. Я не понимаю, как здесь связан ответ .NET.
eis