Створення символу Unicode з його числа


114

Я хочу відобразити на Яві символ Unicode. Якщо я це роблю, це працює чудово:

String symbol = "\u2202";

символ дорівнює "∂". Це те, що я хочу.

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

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

Однак у цьому випадку символ дорівнює "\ u2202". Це не те, що я хочу.

Як я можу побудувати символ, якщо я знаю його номер Unicode (але лише під час виконання --- я не можу жорстко кодувати його, як перший приклад)?


1
Видаліть перший косий ривок, щоб замість того, щоб уникнути зворотної косої риски, уникнути послідовності Unicode Використання "\\" повідомляє Java, що ви хочете роздрукувати "\", а не використовувати його як минулу послідовність евакуації для символів Unicode. Якщо ви вилучите перший, то він замість цього дозволить уникнути послідовності Unicode, а не другої косої риски. Принаймні, це буде, наскільки мені відомо.
Фонд позову Моніки

Відповіді:


73

Просто Віддайте свій intдо char. Ви можете конвертувати це у Stringкористування Character.toString():

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

Редагувати:

Пам'ятайте лише, що послідовності евакуації у вихідному коді Java ( \uбіти) знаходяться у HEX, тому якщо ви намагаєтесь відтворити послідовність втечі, вам знадобиться щось на зразок int c = 0x2202.


3
Ось просто даю мені квадратний ящик, ࢚. Це не дає мені "∂".
Пол Рейнерс

19
Небезпека, Віл Робінзон! Не забувайте, що кодові точки Unicode не обов'язково вписуються у таблицю . Тож вам потрібно бути впевненими заздалегідь, що ваше значення 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, що зберігається у масиві char. Якщо вказаною кодовою точкою є значення BMP (Basic Multilingual Plane або Plane 0), отриманий масив char має те саме значення, що і codePoint. Якщо вказана кодова точка є додатковою кодовою точкою, отриманий масив знаків має відповідну сурогатну пару.


Хоча це більш загальне рішення і в багатьох випадках ви повинні використовувати це над прийнятою відповіддю, прийнята відповідь є більш близькою до конкретної проблеми, про яку Павло попросив.
Джохем Куджперс

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 ...?" , і прийнята відповідь не може працювати, якщо "номер Unicode" знаходиться поза BMP. Наприклад, прийнята відповідь не відповідає дійсній кодовій точці 0x1040C, оскільки вона знаходиться в SMP. Це погана відповідь, і її слід виправити чи видалити.
skomisa

Сценарій ОП @skomisa обмежується представленням шістнадцяткової послідовності виходу Unicode. Якщо у вас є персонаж, який повинен бути закодований як сурогатна пара, то це відображається в цих послідовностях втечі, тож він все-таки виходить у підсумку. Як я вже сказав, це більш загальне рішення, і вам слід скористатися цим.
Джохем Куджперс

20

Інші відповіді тут або підтримують лише унікод до 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 не може відтворити проблему, працює однаково добре для мене
EIS

Кудо за те, що йти далі. Для str4призначення це не повинно codeбути codePointзамість цього?
skomisa

6

Пам'ятайте, що charце інтегральний тип, і таким чином можна надати ціле значення, а також константа знаку.

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

Ось просто даю мені квадратний ящик, ࢚. Це не дає мені "∂".
Пол Рейнерс

3
Це тому, що 2202 - це не те, що intви шукали. Ви шукали 0x2202. Моя провина. У будь-якому випадку, якщо у вас є intкодова точка, яку ви шукаєте, ви можете просто віддати її до а charта скористатися нею (щоб побудувати, 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

4
О, ні, тримайся! Значення Unicode (послідовності втечі \ 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 символи unicode (представлені десятковими знаками) для слова "бути" японською мовою. Так, дієслово "бути" японською мовою має 4 знаки! Значення символів знаходиться в десятковій формі і воно зчитується в масив String [] - використовуючи, наприклад, розділення. Якщо у вас вісімковий або шістнадцятковий, аналізуйте також радіацію.

// 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 видає синтаксичну помилку. Причина полягає в тому, що формат Unicode Java Escaped очікує синтаксису "\ uXXXX", де XXXX - це 4 шістнадцяткових цифри, які є обов'язковими. Спроба скласти цю струну з шматочків не вдається. Звичайно, "\ u" - це не те саме, що "\\ u". Перший синтаксис означає уникнути 'u', другий означає униклий люфт (який є люфтом), а потім 'u'. Дивно, що на сторінках Apache представлена ​​утиліта, яка виконує саме таку поведінку. Але насправді це - мімічна утиліта Escape . Apache має деякі власні утиліти (я їх не перевіряв), які роблять це для вас. Можливо, це все-таки не те, що ви хочете мати.Але ця утиліта 1 добре підходить до рішення. Із описаною вище комбінацією (MeraNaamJoker). Моє рішення - створити цей мімічний рядок Escaped, а потім перетворити його назад в unicode (щоб уникнути реального обмеження Unicode 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);

Тепер х - ваша відповідь. Але це HEX за допомогою HEX перетворення та перетворення речень у речення - це робота для дослідників: P


питання справді до Java. Я не бачу, як тут пов'язана відповідь .NET.
eis
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.