Erstellen eines Unicode-Zeichens aus seiner Nummer

114

Ich möchte ein Unicode-Zeichen in Java anzeigen. Wenn ich das mache, funktioniert es einwandfrei:

String symbol = "\u2202";

Symbol ist gleich "∂". Das ist, was ich will.

Das Problem ist, dass ich die Unicode-Nummer kenne und daraus das Unicode-Symbol erstellen muss. Ich habe (für mich) das Offensichtliche versucht:

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

In diesem Fall ist das Symbol jedoch gleich "\ u2202". Das will ich nicht.

Wie kann ich das Symbol erstellen, wenn ich seine Unicode-Nummer kenne (aber nur zur Laufzeit --- ich kann es nicht wie im ersten Beispiel fest codieren)?

Paul Reiners
quelle
1
Entfernen Sie den ersten Backslash, damit er nicht dem Backslash, sondern der Unicode-Sequenz entgeht. Die Verwendung von "\\" teilt Java mit, dass Sie "\" ausdrucken möchten, und nicht als Vergangenheit einer Escape-Sequenz für Unicode-Zeichen. Wenn Sie die erste entfernen, wird stattdessen die Unicode-Sequenz und nicht der zweite Backslash ausgeblendet. Zumindest wird es nach bestem Wissen und Gewissen.
Fund Monica Klage

Antworten:

73

Wirf einfach deine intzu einem char. Sie können das in ein Stringusing konvertieren Character.toString():

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

BEARBEITEN:

Denken Sie daran, dass sich die Escape-Sequenzen im Java-Quellcode (die \uBits) in HEX befinden. Wenn Sie also versuchen, eine Escape-Sequenz zu reproduzieren, benötigen Sie so etwas wie int c = 0x2202.

dty
quelle
3
Das gibt mir nur eine quadratische Schachtel, ࢚. Es gibt mir nicht "∂".
Paul Reiners
18
Gefahr, Will Robinson! Vergessen Sie nicht, dass Unicode-Codepunkte nicht unbedingt in ein Zeichen passen . Sie müssen also im cVoraus absolut sicher sein, dass Ihr Wert kleiner als 0x10000 ist, sonst wird dieser Ansatz schrecklich brechen.
David gegeben
1
@NickHartley Sorry, folge nicht --- hast du 0x10000 für 10000 falsch gelesen?
David gegeben
10
Deshalb habe ich unten 'gesagt'! Und ich muss betonen, dass Unicode-Codepunkte trotz der Tatsache, dass Java-Zeichen nur bis zu 0xffff reichen, bis zu 0xfffff reichen. Der Unicode-Standard wurde nach dem Entwurf von Java geändert. Heutzutage enthalten Java-Zeichen technisch gesehen UTF-16-Wörter und keine Unicode-Codepunkte. Wenn Sie dies vergessen, wird dies zu einem schrecklichen Bruch führen, wenn Ihre Anwendung auf ein exotisches Skript stößt.
David gegeben
3
@ DavidGiven danke für Java chars go up to 0xFFFF. Ich wusste das nicht.
Tony Ennis
128

Wenn Sie eine UTF-16-codierte Codeeinheit als erhalten möchten char, können Sie die Ganzzahl analysieren und wie von anderen vorgeschlagen in sie umwandeln .

Wenn Sie alle Codepunkte unterstützen möchten, verwenden Sie Character.toChars(int). Dies behandelt Fälle, in denen Codepunkte nicht in einen einzelnen charWert passen .

Doc sagt:

Konvertiert das angegebene Zeichen (Unicode-Codepunkt) in seine UTF-16-Darstellung, die in einem char-Array gespeichert ist. Wenn der angegebene Codepunkt ein BMP-Wert (Basic Multilingual Plane oder Plane 0) ist, hat das resultierende char-Array denselben Wert wie codePoint. Wenn der angegebene Codepunkt ein zusätzlicher Codepunkt ist, hat das resultierende char-Array das entsprechende Ersatzpaar.

McDowell
quelle
Während dies eine allgemeinere Lösung ist und Sie dies in vielen Fällen über der akzeptierten Antwort verwenden sollten, entspricht die akzeptierte Antwort eher dem spezifischen Problem, nach dem Paul gefragt hat.
Jochem Kuijpers
2
Erstens danke! In Scala kann ich immer noch keine Zeichen analysieren, die größer als a sind char. scala> "👨‍🎨".map(_.toInt).flatMap((i: Int) => Character.toChars(i)).map(_.toHexString)gibt res11: scala.collection.immutable.IndexedSeq[String] = Vector(f468, 200d, f3a8) Dieses Emoji, "männlicher Sänger", wird mit den drei Codepunkten angesprochen U+1f468, U+200dund U+1f3a8. Die höchstwertige Ziffer fehlt. Ich kann es mit einem bitweisen ODER hinzufügen ( stackoverflow.com/a/2220476/1007926 ), weiß aber nicht, wie ich feststellen soll, welche analysierten Zeichen abgeschnitten wurden. Vielen Dank!
Peter Becich
1
@JochemKuijpers Ich stimme nicht zu, dass "die akzeptierte Antwort dem spezifischen Problem näher kommt" . Das OP fragte ausdrücklich: "Wie kann ich das Symbol konstruieren, wenn ich seine Unicode-Nummer kenne ...?" und die akzeptierte Antwort kann nicht funktionieren, wenn sich diese "Unicode-Nummer" außerhalb des BMP befindet. Beispielsweise schlägt die akzeptierte Antwort für den gültigen Codepunkt 0x1040C fehl, da er sich im SMP befindet. Es ist eine schlechte Antwort und sollte korrigiert oder gelöscht werden.
Skomisa
Das @ skomisa OPs-Szenario beschränkt sich auf die Darstellung der hexadezimalen Unicode-Escape-Sequenz. Wenn Sie ein Zeichen haben, das als Ersatzpaar codiert werden soll, spiegelt sich dies in diesen Escape-Sequenzen wider, sodass es am Ende immer noch funktioniert. Wie gesagt, dies ist eine allgemeinere Lösung, und Sie sollten diese verwenden.
Jochem Kuijpers
20

Die anderen Antworten hier unterstützen entweder nur Unicode bis U + FFFF (die Antworten, die sich nur mit einer Instanz von char befassen) oder geben nicht an, wie zum eigentlichen Symbol zu gelangen ist (die Antworten, die bei Character.toChars () enden oder eine falsche Methode verwenden) danach), also füge auch hier meine Antwort hinzu.

Um auch zusätzliche Codepunkte zu unterstützen, muss Folgendes getan werden:

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

Ich habe auch schnell getestet, welche Konvertierungsmethoden funktionieren und welche nicht

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
quelle
Wie kommt es, dass es als Einzeiler nicht funktioniert? new String(Character.toChars(121849));bricht in der Eclipse-Konsole, aber die dreizeilige Version funktioniert.
Noumenon
@ Noumenon kann das Problem nicht reproduzieren, funktioniert genauso gut für mich
Eis
Ein großes Lob für die Weiterentwicklung. Für die str4Zuordnung sollte nicht codesein , codePointstatt?
Skomisa
6

Denken Sie daran, dass dies charein integraler Typ ist und daher ein ganzzahliger Wert sowie eine Zeichenkonstante angegeben werden kann.

char c = 0x2202;//aka 8706 in decimal. \u codepoints are in hex.
String s = String.valueOf(c);
ILMTitan
quelle
Das gibt mir nur eine quadratische Schachtel, ࢚. Es gibt mir nicht "∂".
Paul Reiners
3
Das liegt daran, dass 2202 nicht das ist, wonach intSie gesucht haben. Sie haben nach 0x2202 gesucht. Mein Fehler. In jedem Fall können Sie, wenn Sie intden gewünschten Codepunkt haben, ihn einfach in a umwandeln charund verwenden (um einen zu erstellen, Stringwenn Sie dies wünschen).
ILMTitan
6

Dieser hat gut für mich funktioniert.

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

Jetzt hat text2 ∂.

MeraNaamJoker
quelle
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
quelle
1
Während dieser Beitrag möglicherweise die Frage beantwortet, ist eine Erklärung erforderlich, was Sie tun. um die Qualität und Lesbarkeit Ihrer Antwort zu verbessern
Ajil O.
1
Danke, es hat mir wirklich geholfen! Funktioniert gut und ist einfacher als andere Lösungen hier (wirklich, Java-Leute mögen es so sehr, Dinge zu komplizieren).
Parsecer
2

Das ist wie man es macht:

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

Diese Lösung stammt von Arne Vajhøj.

Paul Reiners
quelle
Wollen Sie damit sagen, dass dies funktioniert? Wenn ja, funktioniert dies, weil Sie zweitausend, zweihundertzwei als 0x2202 neu interpretieren, was natürlich überhaupt nicht dasselbe ist.
dty
4
Oh nein, warte! Die Unicode-Werte (die Escape-Sequenzen in der Java-Quelle) sind hexadezimal! Das ist also richtig. Sie haben einfach alle in die Irre geführt, indem Sie gesagt haben int c = 2202, was falsch ist! Eine bessere Lösung als diese ist einfach zu sagen, int c = 0x2202die Sie
erspart
3
+1 @dty: Es gibt absolut keinen Anruf für die char ccc...Mittellinie. Verwenden Sie einfach int cc = 0x2202;und dannfinal String text=String.valueOf(cc);
Andrew Coonce
2

Obwohl dies eine alte Frage ist, gibt es in Java 11, das heute veröffentlicht wurde, eine sehr einfache Möglichkeit, dies zu tun: Sie können eine neue Überladung von Character.toString () verwenden :

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

Da diese Methode jeden Unicode-Codepunkt unterstützt, beträgt die Länge des zurückgegebenen Strings nicht unbedingt 1.

Der Code, der für das in der Frage angegebene Beispiel benötigt wird, lautet einfach:

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

Dieser Ansatz bietet mehrere Vorteile:

  • Es funktioniert für jeden Unicode-Codepunkt und nicht nur für diejenigen, die mit a verarbeitet werden können char.
  • Es ist prägnant und leicht zu verstehen, was der Code tut.
  • Der Wert wird eher als Zeichenfolge als als a zurückgegeben char[], was häufig gewünscht wird. Die von McDowell gepostete Antwort ist angemessen, wenn Sie den Codepunkt als zurückgeben möchten char[].
Skomisa
quelle
Einige zusätzliche Erläuterungen zu diesem Thema, da diese Antwort mir sofort klar machte, wie die CodePoint-Variable erstellt wird. Die Syntax hier sollte lauten: int codePoint = 0x2202;Dann: String s = Character.toString(codePoint); // <<< Requires JDK 11 !!! Oder in einem System.out.println(Character.toString(0x2202)); // Prints ∂
Einzeiler
1

Der folgende Code schreibt die 4 Unicode-Zeichen (durch Dezimalstellen dargestellt) für das Wort "be" auf Japanisch. Ja, das japanische Verb "be" hat 4 Zeichen! Der Wert der Zeichen ist dezimal und wurde in ein Array von String [] eingelesen - beispielsweise mit split. Wenn Sie Octal oder Hex haben, parseInt nehmen auch eine Radix.

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

Hier ist ein Block Unicode - Zeichen drucken zwischen \u00c0zu \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
quelle
0

Leider führt das Entfernen eines Spiels, wie im ersten Kommentar erwähnt (newbiedoodle), nicht zu einem guten Ergebnis. Die meisten (wenn nicht alle) IDE-Probleme verursachen Syntaxfehler. Der Grund dafür ist, dass das Java Escaped Unicode-Format die Syntax "\ uXXXX" erwartet, wobei XXXX 4 hexadezimale Ziffern sind, die obligatorisch sind. Versuche, diese Saite aus Stücken zu falten, schlagen fehl. Natürlich ist "\ u" nicht dasselbe wie "\\ u". Die erste Syntax bedeutet "u" maskiert, die zweite bedeutet "Escape" (gefolgt von "u"). Es ist seltsam, dass auf den Apache-Seiten ein Dienstprogramm vorgestellt wird, das genau dieses Verhalten ausführt. In Wirklichkeit ist es jedoch ein Escape-Mimic-Dienstprogramm . Apache hat einige eigene Dienstprogramme (ich habe sie nicht getestet), die diese Arbeit für Sie erledigen. Vielleicht ist es immer noch nicht das, was du haben willst.Dieses Dienstprogramm hat jedoch 1 hateinen guten Lösungsansatz. Mit der oben beschriebenen Kombination (MeraNaamJoker). Meine Lösung besteht darin, diesen Escaped-Mimic-String zu erstellen und ihn dann wieder in Unicode zu konvertieren (um echte Escaped-Unicode-Einschränkungen zu vermeiden). Ich habe es zum Kopieren von Text verwendet, daher ist es möglich, dass in der Uencode-Methode die Verwendung von '\\ u' mit Ausnahme von '\\\\ u' besser ist. Versuch es.

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

char c = (char) 0x2202; String s = "" + c;

dave110022
quelle
-7

(ANTWORT IST IN DOT NET 4.5 und in Java muss es einen ähnlichen Ansatz geben)

Ich komme aus Westbengalen in Indien. Soweit ich weiß, ist Ihr Problem ... Sie möchten ähnlich wie 'অ' (es ist ein Buchstabe in bengalischer Sprache) mit Unicode HEX produzieren:0X0985 .

Wenn Sie diesen Wert in Bezug auf Ihre Sprache kennen, wie werden Sie dann dieses sprachspezifische Unicode-Symbol richtig erzeugen?

In Dot Net ist das so einfach:

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

Jetzt ist x deine Antwort. Aber dies ist HEX by HEX-Konvertierung und Satz-zu-Satz-Konvertierung ist eine Arbeit für Forscher: P.

Suman Kr. Nath
quelle
Frage ist in der Tat für Java. Ich sehe nicht, wie die .NET-Antwort hier zusammenhängt.
uvb