Création d'un caractère Unicode à partir de son numéro

114

Je souhaite afficher un caractère Unicode en Java. Si je fais cela, cela fonctionne très bien:

String symbol = "\u2202";

le symbole est égal à "∂". C'est ce que je veux.

Le problème est que je connais le numéro Unicode et que je dois créer le symbole Unicode à partir de cela. J'ai essayé (pour moi) la chose évidente:

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

Cependant, dans ce cas, le symbole est égal à "\ u2202". Ce n'est pas ce que je veux.

Comment puis-je construire le symbole si je connais son numéro Unicode (mais seulement au moment de l'exécution - je ne peux pas le coder en dur comme le premier exemple)?

Paul Reiners
la source
1
Supprimez la première barre oblique inverse, de sorte qu'au lieu d'échapper la barre oblique inverse, elle échappe la séquence Unicode. L'utilisation de "\\" indique à Java que vous souhaitez imprimer "\", et non pas l'utiliser comme passé d'une séquence d'échappement pour les caractères Unicode. Si vous supprimez le premier, il échappera à la place à la séquence Unicode et non à la deuxième barre oblique inverse. Du moins, au mieux de ma connaissance.
Fund Monica's Lawsuit

Réponses:

73

Il suffit de lancer votre fichier intsur un fichier char. Vous pouvez convertir cela en une Stringutilisation Character.toString():

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

ÉDITER:

N'oubliez pas que les séquences d'échappement dans le code source Java (les \ubits) sont en HEX, donc si vous essayez de reproduire une séquence d'échappement, vous aurez besoin de quelque chose comme int c = 0x2202.

dty
la source
3
Cela me donne juste une boîte carrée, ࢚. Ça ne me donne pas "∂".
Paul Reiners
19
Danger, Will Robinson! N'oubliez pas que les points de code Unicode ne rentreront pas nécessairement dans un caractère . Vous devez donc être absolument sûr à l'avance que votre valeur de cest inférieure à 0x10000, sinon cette approche se cassera horriblement.
David donné
1
@NickHartley Désolé, ne suivez pas --- avez-vous mal lu 0x10000 pour 10000?
David donné le
10
C'est pourquoi j'ai dit «ci-dessous»! Et je dois souligner que, malgré le fait que les caractères Java ne montent que vers 0xffff, les points de code Unicode vont jusqu'à 0xfffff. La norme Unicode a été modifiée après la conception de Java. Ces jours-ci, les caractères Java contiennent techniquement des mots UTF-16, pas des points de code Unicode, et l'oublier entraînera une rupture hideuse lorsque votre application rencontrera un script exotique.
David donné le
3
@DavidGiven merci pour Java chars go up to 0xFFFF. Je ne savais pas ça.
Tony Ennis
128

Si vous souhaitez obtenir une unité de code encodée en UTF-16 en tant que char, vous pouvez analyser l'entier et le convertir comme d'autres l'ont suggéré.

Si vous souhaitez prendre en charge tous les points de code, utilisez Character.toChars(int). Cela gérera les cas où les points de code ne peuvent pas tenir dans une seule charvaleur.

Doc dit:

Convertit le caractère spécifié (point de code Unicode) en sa représentation UTF-16 stockée dans un tableau de caractères. Si le point de code spécifié est une valeur BMP (Basic Multilingual Plane ou Plane 0), le tableau de caractères résultant a la même valeur que codePoint. Si le point de code spécifié est un point de code supplémentaire, le tableau de caractères résultant a la paire de substitution correspondante.

McDowell
la source
Bien qu'il s'agisse d'une solution plus générale et que, dans de nombreux cas, vous devriez l'utiliser par rapport à la réponse acceptée, la réponse acceptée correspond plus étroitement au problème spécifique que Paul a demandé.
Jochem Kuijpers
2
Tout d'abord merci! Dans Scala, je ne parviens toujours pas à analyser les caractères supérieurs à un char. scala> "👨‍🎨".map(_.toInt).flatMap((i: Int) => Character.toChars(i)).map(_.toHexString)donne res11: scala.collection.immutable.IndexedSeq[String] = Vector(f468, 200d, f3a8) Cet emoji, "chanteur masculin", est adressé avec les trois points de code U+1f468, U+200det U+1f3a8. Le chiffre le plus significatif est manquant. Je peux l'ajouter avec un OU au niveau du bit ( stackoverflow.com/a/2220476/1007926 ), mais je ne sais pas comment déterminer quels caractères analysés ont été tronqués. Merci!
Peter Becich
1
@JochemKuijpers Je ne suis pas d'accord pour dire que "la réponse acceptée correspond plus étroitement au problème spécifique" . L'OP a explicitement demandé "Comment puis-je construire le symbole si je connais son numéro Unicode ...?" , et la réponse acceptée ne peut pas fonctionner si ce "numéro Unicode" est en dehors du BMP. Par exemple, la réponse acceptée échoue pour le point de code valide 0x1040C car il se trouve dans le SMP. C'est une mauvaise réponse et devrait être corrigée ou supprimée.
skomisa
Le scénario @skomisa OPs est limité à la représentation de la séquence d'échappement Unicode hexadécimale. Si vous avez un caractère qui doit être codé comme une paire de substitution, cela se reflète dans ces séquences d'échappement, donc cela fonctionne toujours à la fin. Comme je l'ai dit, c'est une solution plus générale et vous devriez l'utiliser.
Jochem Kuijpers
20

Les autres réponses ici ne prennent en charge que l'unicode jusqu'à U + FFFF (les réponses ne traitant qu'une seule instance de char) ou ne disent pas comment accéder au symbole réel (les réponses s'arrêtant à Character.toChars () ou en utilisant une méthode incorrecte après cela), donc en ajoutant ma réponse ici aussi.

Pour prendre en charge également les points de code supplémentaires, voici ce qui doit être fait:

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

J'ai également fait un test rapide pour savoir quelles méthodes de conversion fonctionnent et lesquelles ne fonctionnent pas

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
eis
la source
Pourquoi cela ne fonctionne-t-il pas comme une seule ligne? new String(Character.toChars(121849));casse dans la console Eclipse, mais la version à trois lignes fonctionne.
Noumenon le
@Noumenon ne peut pas reproduire le problème, fonctionne tout aussi bien pour moi
eis
Bravo pour aller plus loin. Pour le str4devoir, ne devrait pas codeêtre à la codePointplace?
skomisa
6

Rappelez-vous qu'il chars'agit d'un type intégral et que vous pouvez donc lui attribuer une valeur entière, ainsi qu'une constante char.

char c = 0x2202;//aka 8706 in decimal. \u codepoints are in hex.
String s = String.valueOf(c);
ILMTitan
la source
Cela me donne juste une boîte carrée, ࢚. Ça ne me donne pas "∂".
Paul Reiners
3
C'est parce que 2202 n'est pas celui que intvous recherchiez. Vous recherchiez 0x2202. Ma faute. Dans tous les cas, si vous avez le intpoint de code que vous recherchez, vous pouvez simplement le convertir en a charet l'utiliser (pour construire a Stringsi vous le souhaitez).
ILMTitan
6

Celui-ci a bien fonctionné pour moi.

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

Maintenant, text2 aura ∂.

MeraNaamJoker
la source
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'.
Kapil K. Kushwah
la source
1
Bien que ce message puisse répondre à la question, une explication est nécessaire sur ce que vous faites; pour améliorer la qualité et la lisibilité de votre réponse
Ajil O.
1
Merci, cela m'a vraiment aidé! Fonctionne bien et est plus facile que les autres solutions ici (vraiment, les gens de Java aiment tellement compliquer les choses).
parsecer le
2

Voici comment vous procédez:

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

Cette solution est d'Arne Vajhøj.

Paul Reiners
la source
Êtes-vous en train de dire que cela fonctionne? Si tel est le cas, cela fonctionne parce que vous réinterprétez deux mille deux cent deux en 0x2202, ce qui, bien sûr, n'est pas du tout la même chose.
dty
4
Oh non, attendez! Les valeurs Unicode (les séquences d'échappement \ u dans la source Java) SONT hex! Donc c'est vrai. Vous venez de tromper tout le monde en disant int c = 2202, ce qui est faux! Une meilleure solution que cela est simple à dire int c = 0x2202qui vous évitera de passer via une chaîne, etc.
dty
3
+1 @dty: Il n'y a absolument aucun appel pour la char ccc...ligne médiane . Il suffit d'utiliser int cc = 0x2202;et puisfinal String text=String.valueOf(cc);
Andrew Coonce
2

Bien que ce soit une vieille question, il existe un moyen très simple de le faire dans Java 11 qui a été publié aujourd'hui: vous pouvez utiliser une nouvelle surcharge de 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

Étant donné que cette méthode prend en charge n'importe quel point de code Unicode, la longueur de la chaîne renvoyée n'est pas nécessairement 1.

Le code nécessaire pour l'exemple donné dans la question est simplement:

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

Cette approche offre plusieurs avantages:

  • Cela fonctionne pour n'importe quel point de code Unicode plutôt que pour ceux qui peuvent être gérés à l'aide d'un char.
  • C'est concis et il est facile de comprendre ce que fait le code.
  • Il renvoie la valeur sous forme de chaîne plutôt que de a char[], ce qui est souvent ce que vous voulez. La réponse publiée par McDowell est appropriée si vous souhaitez que le point de code soit renvoyé sous la forme char[].
skomisa
la source
Quelques précisions supplémentaires sur celui-ci, car cette réponse m'a immédiatement rendu évidente comment créer la variable codePoint. La syntaxe ici devrait être: int codePoint = 0x2202;Ensuite: String s = Character.toString(codePoint); // <<< Requires JDK 11 !!! Ou en une seule ligne: System.out.println(Character.toString(0x2202)); // Prints ∂ J'espère que cela aidera quelqu'un d'autre à utiliser cette fonctionnalité du JDK 11.
Loathian
1

Le code ci-dessous écrira les 4 caractères unicode (représentés par des décimales) pour le mot «être» en japonais. Oui, le verbe «être» en japonais a 4 caractères! La valeur des caractères est en décimal et elle a été lue dans un tableau de String [] - en utilisant par exemple split. Si vous avez Octal ou Hex, parseInt prend également une base de données.

// 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
la source
1

Voici un bloc pour imprimer les caractères unicode entre \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
la source
0

Malheureusement, supprimer un jeu comme mentionné dans le premier commentaire (newbiedoodle) ne conduit pas à un bon résultat. La plupart (sinon tous) IDE émet des erreurs de syntaxe. La raison en est que le format Java Escaped Unicode attend la syntaxe "\ uXXXX", où XXXX correspond à 4 chiffres hexadécimaux, qui sont obligatoires. Les tentatives de pliage de cette chaîne à partir de morceaux échouent. Bien sûr, "\ u" n'est pas la même chose que "\\ u". La première syntaxe signifie «u» échappé, la seconde signifie une réaction d'échappement (qui est une réaction) suivie de «u». Il est étrange que sur les pages Apache est présenté un utilitaire, qui fait exactement ce comportement. Mais en réalité, c'est l' utilitaire mimique d'Escape . Apache a ses propres utilitaires (je ne les ai pas testés), qui font ce travail pour vous. Peut-être, ce n'est toujours pas ça, ce que vous voulez avoir.Mais cet utilitaireavoir une bonne approche de la solution. Avec la combinaison décrite ci-dessus (MeraNaamJoker). Ma solution est de créer cette chaîne synoptique Escaped, puis de la reconvertir en Unicode (pour éviter une véritable restriction Unicode Escaped). Je l'ai utilisé pour copier du texte, il est donc possible que, dans la méthode uencode, il soit préférable d'utiliser '\\ u' sauf '\\\\ u'. Essayez-le.

  /**
   * 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;
  }
hariprasad
la source
-1

char c = (char) 0x2202; Chaîne s = "" + c;

dave110022
la source
-7

(RÉPONSE EST DANS DOT NET 4.5 et en java, il doit exister une approche similaire)

Je viens du Bengale occidental en Inde. Si je comprends bien, votre problème est ... Vous voulez produire un produit similaire à 'অ' (c'est une lettre en bengali) qui a Unicode HEX:0X0985 .

Maintenant, si vous connaissez cette valeur par rapport à votre langue, comment allez-vous produire ce symbole Unicode spécifique à la langue, n'est-ce pas?

Dans Dot Net, c'est aussi simple que ceci:

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

Maintenant, x est votre réponse. Mais c'est HEX par HEX converti et la conversion de phrase en phrase est un travail pour les chercheurs: P

Suman Kr. Nath
la source
la question est en effet pour java. Je ne vois pas comment la réponse .NET est liée ici.
eis le