Creazione del carattere Unicode dal suo numero


114

Voglio visualizzare un carattere Unicode in Java. Se lo faccio, funziona perfettamente:

String symbol = "\u2202";

il simbolo è uguale a "∂". È quello che voglio.

Il problema è che conosco il numero Unicode e da quello devo creare il simbolo Unicode. Ho provato (per me) la cosa ovvia:

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

Tuttavia, in questo caso, il simbolo è uguale a "\ u2202". Non è quello che voglio.

Come posso costruire il simbolo se conosco il suo numero Unicode (ma solo in fase di esecuzione --- non posso codificarlo come nel primo esempio)?


1
Rimuovere la prima barra rovesciata, in modo che invece di eseguire l'escape della barra rovesciata esca dalla sequenza Unicode. L'utilizzo di "\\" dice a Java che si desidera stampare "\", non usarlo come passato di una sequenza di escape per i caratteri Unicode. Se rimuovi il primo, sarà invece sfuggito alla sequenza Unicode e non al secondo backslash. Almeno, per quanto ne so.
Finanzia la causa di Monica il

Risposte:


73

Trasmetti il ​​tuo inta un file char. Puoi convertirlo in un Stringutilizzo Character.toString():

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

MODIFICARE:

Ricorda solo che le sequenze di escape nel codice sorgente Java (i \ubit) sono in HEX, quindi se stai cercando di riprodurre una sequenza di escape, avrai bisogno di qualcosa di simile int c = 0x2202.


3
Mi sta solo dando una scatola quadrata, ࢚. Non mi dà "∂".
Paul Reiners

19
Pericolo, Will Robinson! Non dimenticare che i punti di codice Unicode non rientrano necessariamente in un carattere . Quindi devi essere assolutamente sicuro in anticipo che il tuo valore di csia inferiore a 0x10000, altrimenti questo approccio si interromperà orribilmente.
David Given

1
@NickHartley Scusa, non seguire --- hai letto male 0x10000 per 10000?
David dato il

10
Ecco perché ho detto "sotto"! E devo sottolineare che, nonostante il fatto che i caratteri Java arrivino solo a 0xffff, i punti di codice Unicode salgono a 0xfffff. Lo standard Unicode è stato modificato dopo la progettazione di Java. Oggigiorno i caratteri Java tecnicamente contengono parole UTF-16, non punti di codice Unicode, e dimenticarlo causerà terribili interruzioni quando la tua applicazione incontra uno script esotico.
David dato il

3
@DavidGiven grazie per Java chars go up to 0xFFFF. Non lo sapevo.
Tony Ennis,

128

Se vuoi ottenere un'unità di codice con codifica UTF-16 come a char, puoi analizzare il numero intero ed eseguire il cast ad esso come altri hanno suggerito.

Se vuoi supportare tutti i punti di codice, usa Character.toChars(int). Ciò gestirà i casi in cui i punti di codice non possono essere contenuti in un singolo charvalore.

Doc dice:

Converte il carattere specificato (punto di codice Unicode) nella relativa rappresentazione UTF-16 archiviata in una matrice di caratteri. Se il punto di codice specificato è un valore BMP (Basic Multilingual Plane o Plane 0), la matrice di caratteri risultante ha lo stesso valore di codePoint. Se il punto di codice specificato è un punto di codice supplementare, la matrice di caratteri risultante ha la coppia surrogata corrispondente.


Sebbene questa sia una soluzione più generale e in molti casi dovresti usarla sopra la risposta accettata, la risposta accettata è una corrispondenza più vicina al problema specifico che Paolo ha chiesto.
Jochem Kuijpers

2
In primo luogo, grazie! In Scala, non riesco ancora ad analizzare i caratteri più grandi di un file char. scala> "👨‍🎨".map(_.toInt).flatMap((i: Int) => Character.toChars(i)).map(_.toHexString)res11: scala.collection.immutable.IndexedSeq[String] = Vector(f468, 200d, f3a8) Questa emoji, "cantante maschio", è indirizzata con i tre punti di codice U+1f468, U+200de U+1f3a8. Manca la cifra più significativa. Posso aggiungerlo con un OR bit per bit ( stackoverflow.com/a/2220476/1007926 ), ma non so come determinare quali caratteri analizzati sono stati troncati. Grazie!
Peter Becich

1
@JochemKuijpers Non sono d'accordo che "la risposta accettata è una corrispondenza più vicina al problema specifico" . L'OP ha chiesto esplicitamente "Come posso costruire il simbolo se conosco il suo numero Unicode ...?" e la risposta accettata non può funzionare se il "numero Unicode" è esterno al BMP. Ad esempio, la risposta accettata non riesce per il codepoint valido 0x1040C perché si trova nell'SMP. È una risposta scadente e dovrebbe essere corretta o eliminata.
skomisa

Lo scenario di @skomisa OPs è limitato alla rappresentazione della sequenza di escape Unicode esadecimale. Se hai un personaggio che dovrebbe essere codificato come coppia surrogata, questo si riflette in queste sequenze di escape, quindi alla fine funziona comunque. Come ho detto, questa è una soluzione più generale e dovresti usarla.
Jochem Kuijpers

20

Le altre risposte qui supportano solo unicode fino a U + FFFF (le risposte che trattano solo un'istanza di char) o non dicono come arrivare al simbolo effettivo (le risposte si fermano a Character.toChars () o utilizzano un metodo errato dopo di che), quindi aggiungendo anche la mia risposta qui.

Per supportare anche i punti di codice supplementari, questo è ciò che deve essere fatto:

// 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));

Ho anche fatto un rapido test su quali metodi di conversione funzionano e quali no

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

Come mai non funziona come one-liner? new String(Character.toChars(121849));si interrompe nella console Eclipse, ma la versione a tre righe funziona.
Noumenon

@Noumenon non può riprodurre il problema, funziona altrettanto bene per me
eis

Complimenti per andare oltre. Per l' str4incarico, non dovrebbe codeessere codePointinvece?
skomisa

6

Ricorda che charè un tipo integrale e quindi può essere assegnato un valore intero, oltre a una costante char.

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

Mi sta solo dando una scatola quadrata, ࢚. Non mi dà "∂".
Paul Reiners

3
Questo perché 2202 non è quello intche stavi cercando. Stavi cercando 0x2202. Colpa mia. In ogni caso, se hai il intpunto di codice che stai cercando, puoi semplicemente lanciarlo su a char, e usarlo (per costruire a Stringse lo desideri).
ILMTitan

6

Questo ha funzionato bene per me.

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

Ora text2 avrà ∂.


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
Sebbene questo post possa rispondere alla domanda, è necessaria una spiegazione su ciò che stai facendo; per migliorare la qualità e la leggibilità della tua risposta
Ajil O.

1
Grazie, mi ha davvero aiutato! Funziona bene ed è più facile di altre soluzioni qui (in realtà, alle persone Java piace così tanto complicare le cose).
parsecer

2

Ecco come lo fai:

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

Questa soluzione è di Arne Vajhøj.


Stai dicendo che funziona? Se è così, funziona perché stai reinterpretando duemiladuecentodue come 0x2202, il che, ovviamente, non è affatto la stessa cosa.
dty

4
Oh no, aspetta! I valori Unicode (le sequenze di escape \ u nel sorgente Java) SONO esadecimali! Quindi questo è giusto. Hai semplicemente fuorviato tutti dicendo int c = 2202, il che è sbagliato! Una soluzione migliore di questa è semplice da dire int c = 0x2202che ti salverà
dall'uso di

3
+1 @dty: non c'è assolutamente nessuna chiamata per la char ccc...linea di mezzo . Usa int cc = 0x2202;e poifinal String text=String.valueOf(cc);
Andrew Coonce

2

Sebbene questa sia una vecchia domanda, esiste un modo molto semplice per farlo in Java 11, che è stato rilasciato oggi: puoi usare un nuovo overload di 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

Poiché questo metodo supporta qualsiasi punto di codice Unicode, la lunghezza della stringa restituita non è necessariamente 1.

Il codice necessario per l'esempio fornito nella domanda è semplicemente:

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

Questo approccio offre diversi vantaggi:

  • Funziona per qualsiasi punto di codice Unicode anziché solo per quelli che possono essere gestiti utilizzando un file char.
  • È conciso ed è facile capire cosa sta facendo il codice.
  • Restituisce il valore come una stringa anziché come un char[], che spesso è ciò che desideri. La risposta pubblicata da McDowell è appropriata se si desidera che il punto di codice venga restituito come char[].

Alcuni chiarimenti aggiuntivi su questo dato che questa risposta mi ha reso immediatamente ovvio come creare la variabile codePoint. La sintassi qui dovrebbe essere: int codePoint = 0x2202;Quindi: String s = Character.toString(codePoint); // <<< Requires JDK 11 !!! O in una System.out.println(Character.toString(0x2202)); // Prints ∂
riga

1

Il codice seguente scriverà i 4 caratteri Unicode (rappresentati da decimali) per la parola "be" in giapponese. Sì, il verbo "essere" in giapponese ha 4 caratteri! Il valore dei caratteri è in decimale ed è stato letto in un array di String [], ad esempio utilizzando split. Se hai Octal o Hex, parseInt prende anche una radice.

// 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

Qui è un blocco di stampare caratteri unicode tra \u00c0a \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

Sfortunatamente, rimuovere un backlash come menzionato nel primo commento (newbiedoodle) non porta a buoni risultati. La maggior parte (se non tutti) IDE genera un errore di sintassi. Il motivo è in questo, che il formato Unicode con escape Java richiede la sintassi "\ uXXXX", dove XXXX sono 4 cifre esadecimali, che sono obbligatorie. I tentativi di piegare questa stringa dai pezzi falliscono. Ovviamente "\ u" non è la stessa cosa di "\\ u". La prima sintassi significa "u" con escape, la seconda significa backlash con escape (che è backlash) seguito da "u". È strano, che sulle pagine di Apache sia presentata un'utilità, che fa esattamente questo comportamento. Ma in realtà, è l' utilità Escape mimic . Apache ha alcune proprie utilità (non le ho testate), che fanno questo lavoro per te. Può essere, non è ancora quello che vuoi avere.Ma questa utility 1 ha un buon approccio alla soluzione. Con la combinazione sopra descritta (MeraNaamJoker). La mia soluzione è creare questa stringa mimica Escaped e quindi riconvertirla in Unicode (per evitare la vera restrizione Unicode Escaped). L'ho usato per copiare il testo, quindi è possibile che nel metodo uencode sia meglio usare '\\ u' tranne '\\\\ u'. Provalo.

  /**
   * 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

(LA RISPOSTA È IN DOT NET 4.5 e in java, deve esistere un approccio simile)

Vengo dal Bengala occidentale in INDIA. A quanto ho capito il tuo problema è ... Vuoi produrre qualcosa di simile a 'অ' (è una lettera in lingua bengalese) che ha Unicode HEX:0X0985 .

Ora, se conosci questo valore rispetto alla tua lingua, come farai a produrre quel simbolo Unicode specifico per la lingua, giusto?

In Dot Net è così semplice:

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

Ora x è la tua risposta. Ma questo è HEX di HEX convert e la conversione da frase a frase è un lavoro per i ricercatori: P


la domanda è davvero per Java. Non vedo come la risposta .NET sia correlata qui.
eis
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.