Criação de caractere Unicode a partir de seu número

114

Quero exibir um caractere Unicode em Java. Se eu fizer isso, funcionará perfeitamente:

String symbol = "\u2202";

símbolo é igual a "∂". Isso é o que eu quero.

O problema é que eu sei o número Unicode e preciso criar o símbolo Unicode a partir dele. Tentei (para mim) o óbvio:

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

No entanto, neste caso, o símbolo é igual a "\ u2202". Não é isso que eu quero.

Como posso construir o símbolo se eu souber seu número Unicode (mas apenas em tempo de execução --- não posso codificá-lo como no primeiro exemplo)?

Paul Reiners
fonte
1
Remova a primeira barra invertida para que, em vez de escapar da barra invertida, escape da sequência Unicode. Usar "\\" informa ao Java que você deseja imprimir "\", não usá-lo como o passado de uma seqüência de escape para caracteres Unicode. Se você remover o primeiro, ele escapará da sequência Unicode e não da segunda barra invertida. Pelo menos, até onde sei.
Ação judicial de Monica de

Respostas:

73

Basta lançar o seu intpara um char. Você pode converter isso em um Stringusando Character.toString():

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

EDITAR:

Lembre-se de que as sequências de escape no código-fonte Java (os \ubits) estão em HEX, portanto, se estiver tentando reproduzir uma sequência de escape, você precisará de algo semelhante int c = 0x2202.

dty
fonte
3
Isso está apenas me dando uma caixa quadrada, ࢚. Não está me dando "∂".
Paul Reiners,
19
Perigo, Will Robinson! Não se esqueça de que os pontos de código Unicode não cabem necessariamente em um caractere . Portanto, você precisa ter certeza absoluta de que o valor de cé menor do que 0x10000, caso contrário, essa abordagem falhará terrivelmente.
David Dado
1
@NickHartley Desculpe, não siga --- você interpretou mal 0x10000 para 10000?
David dado em
10
É por isso que eu disse 'abaixo'! E eu preciso enfatizar que, apesar do fato de que os caracteres Java só vão até 0xffff, os pontos de código Unicode vão até 0xfffff. O padrão Unicode foi alterado depois que o Java foi projetado. Hoje em dia, os caracteres Java contêm tecnicamente palavras UTF-16, não pontos de código Unicode, e esquecer isso causará uma quebra horrível quando seu aplicativo encontrar um script exótico.
David dado em
3
@DavidGiven thanks for Java chars go up to 0xFFFF. Eu não sabia disso.
Tony Ennis
128

Se você deseja obter uma unidade de código codificado em UTF-16 como um char, pode analisar o inteiro e convertê-lo como outros sugeriram.

Se você deseja oferecer suporte a todos os pontos de código, use Character.toChars(int). Isso vai lidar com casos em que os pontos de código não cabem em um únicochar valor.

Doc diz:

Converte o caractere especificado (ponto de código Unicode) em sua representação UTF-16 armazenada em uma matriz char. Se o ponto de código especificado for um valor BMP (Basic Multilingual Plane ou Plane 0), a matriz char resultante terá o mesmo valor que codePoint. Se o ponto de código especificado for um ponto de código suplementar, a matriz de char resultante terá o par substituto correspondente.

McDowell
fonte
Embora essa seja uma solução mais geral e, em muitos casos, você deva usá-la em vez da resposta aceita, a resposta aceita é uma correspondência mais próxima ao problema específico que Paulo pediu.
Jochem Kuijpers
2
Em primeiro lugar, obrigado! Em Scala, ainda não consigo analisar caracteres maiores do que a char. scala> "👨‍🎨".map(_.toInt).flatMap((i: Int) => Character.toChars(i)).map(_.toHexString)res11: scala.collection.immutable.IndexedSeq[String] = Vector(f468, 200d, f3a8) Este emoji, "cantor", é abordado com os três pontos de código U+1f468, U+200de U+1f3a8. O dígito mais significativo está faltando. Posso adicioná-lo com um OR bit a bit ( stackoverflow.com/a/2220476/1007926 ), mas não sei como determinar quais caracteres analisados ​​foram truncados. Obrigado!
Peter Becich
1
@JochemKuijpers Não concordo que "a resposta aceita é mais próxima do problema específico" . O OP perguntou explicitamente "Como posso construir o símbolo se sei seu número Unicode ...?" , e a resposta aceita não funcionará se esse "número Unicode" estiver fora do BMP. Por exemplo, a resposta aceita falha para o ponto de código 0x1040C válido porque está no SMP. É uma resposta pobre e deve ser corrigida ou excluída.
skomisa
O cenário de @skomisa OPs é limitado à representação da sequência de escape hexadecimal Unicode. Se você tiver um caractere que deve ser codificado como um par substituto, isso se refletirá nessas sequências de escape, portanto, ainda funciona no final. Como eu disse, essa é uma solução mais geral e você deve usá-la.
Jochem Kuijpers
20

As outras respostas aqui suportam apenas unicode até U + FFFF (as respostas lidando com apenas uma instância de char) ou não dizem como chegar ao símbolo real (as respostas param em Character.toChars () ou usando método incorreto depois disso), adicionando minha resposta aqui também.

Para oferecer suporte a pontos de código suplementares, isso é o que precisa ser feito:

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

Também fiz um teste rápido para saber quais métodos de conversão funcionam e quais não

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
fonte
Por que não funciona como um one-liner? new String(Character.toChars(121849));quebra no console do Eclipse, mas a versão de três linhas funciona.
Noumenon
@Noumenon não consegue reproduzir o problema, funciona igualmente bem para mim
eis
Parabéns por ter ido mais longe. Para a str4tarefa, não deveria codeser codePoint?
Skomisa
6

Lembre-se de que charé um tipo integral e, portanto, pode receber um valor inteiro, bem como uma constante char.

char c = 0x2202;//aka 8706 in decimal. \u codepoints are in hex.
String s = String.valueOf(c);
ILMTitan
fonte
Isso está apenas me dando uma caixa quadrada, ࢚. Não está me dando "∂".
Paul Reiners,
3
Isso porque 2202 não é o que intvocê procurava. Você estava procurando por 0x2202. Minha culpa. Em qualquer caso, se você tiver o intdo ponto de código que está procurando, poderá apenas convertê-lo em a chare usá-lo (para construir a, Stringse desejar).
ILMTitan
6

Este funcionou bem para mim.

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

Agora o text2 terá ∂.

MeraNaamJoker
fonte
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
fonte
1
Embora esta postagem possa responder à pergunta, é necessária uma explicação sobre o que você está fazendo; para melhorar a qualidade e a legibilidade de sua resposta
Ajil O.
1
Obrigado, realmente me ajudou! Funciona bem e é mais fácil do que outras soluções aqui (na verdade, o pessoal de Java gosta de complicar as coisas).
parsecer
2

É assim que se faz:

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

Esta solução é de Arne Vajhøj.

Paul Reiners
fonte
Você está dizendo que isso funciona? Se for assim, isso funciona porque você está reinterpretando dois mil, duzentos e dois como 0x2202, o que, é claro, não é a mesma coisa.
dty
4
Oh, não, espere! Os valores Unicode (as sequências de escape \ u no código-fonte Java) SÃO hex! Então isso está certo. Você simplesmente enganou a todos dizendo int c = 2202, o que é errado! Uma solução melhor do que essa é simples de dizer, o int c = 0x2202que o salvará de
usar
3
+1 @dty: Não há absolutamente nenhuma chamada para a char ccc...linha do meio . Basta usar int cc = 0x2202;e entãofinal String text=String.valueOf(cc);
Andrew Coonce
2

Embora esta seja uma questão antiga, há uma maneira muito fácil de fazer isso no Java 11, que foi lançado hoje: você pode usar uma nova sobrecarga 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

Como esse método oferece suporte a qualquer ponto de código Unicode, o comprimento da String retornada não é necessariamente 1.

O código necessário para o exemplo dado na pergunta é simplesmente:

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

Essa abordagem oferece várias vantagens:

  • Ele funciona para qualquer ponto de código Unicode, e não apenas para aqueles que podem ser manipulados com um char.
  • É conciso e fácil de entender o que o código está fazendo.
  • Ele retorna o valor como uma string em vez de um char[], que geralmente é o que você deseja. A resposta postada por McDowell é apropriada se você deseja que o ponto de código seja retornado como char[].
Skomisa
fonte
Alguns esclarecimentos adicionais sobre este, pois esta resposta tornou imediatamente óbvio para mim como criar a variável codePoint. A sintaxe aqui deve ser: int codePoint = 0x2202;Então: String s = Character.toString(codePoint); // <<< Requires JDK 11 !!! Ou em uma linha: System.out.println(Character.toString(0x2202)); // Prints ∂ Espero que isso ajude alguém a usar esse recurso do JDK 11.
Loathian
1

O código a seguir escreverá os 4 caracteres unicode (representados por decimais) para a palavra "ser" em japonês. Sim, o verbo "ser" em japonês tem 4 caracteres! O valor dos caracteres está em decimal e foi lido em uma matriz de String [] - usando divisão por exemplo. Se você tiver Octal ou Hex, parseInt também terá um radical.

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

Aqui é um bloco para imprimir caracteres Unicode entre \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();
}
fjiang_ca
fonte
0

Infelizmente, remover uma reação conforme mencionado no primeiro comentário (newbiedoodle) não leva a um bom resultado. A maioria (se não todos) de IDE emite erros de sintaxe. A razão é que o formato Java Escaped Unicode espera a sintaxe "\ uXXXX", onde XXXX são 4 dígitos hexadecimais, que são obrigatórios. As tentativas de dobrar este barbante em pedaços falham. Claro, "\ u" não é o mesmo que "\\ u". A primeira sintaxe significa 'u' de escape, a segunda significa folga de escape (que é a folga) seguida por 'u'. É estranho, que nas páginas do Apache seja apresentado utilitário, que faz exatamente esse comportamento. Mas, na realidade, é um utilitário de simulação de escape. . O Apache tem alguns utilitários próprios (não os testei), que fazem esse trabalho para você. Pode ser, ainda não é isso, o que você quer ter. Mas este utilitário 1 tem uma boa abordagem para a solução. Com a combinação descrita acima (MeraNaamJoker). Minha solução é criar esta string de simulação de escape e, em seguida, convertê-la de volta para Unicode (para evitar a restrição real de escape de Unicode). Eu usei para copiar texto, então é possível que no método uencode seja melhor usar '\\ u' exceto '\\\\ u'. Tente.

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

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

dave110022
fonte
-7

(A RESPOSTA ESTÁ EM DOT NET 4.5 e em java, deve haver uma abordagem semelhante)

Eu sou de West Bengal, na ÍNDIA. Como eu entendo o seu problema é ... Você quer produzir semelhante ao 'অ' (É uma carta na língua bengali), que tem Unicode HEX: 0X0985.

Agora, se você conhece esse valor em relação ao seu idioma, como produzirá esse símbolo Unicode específico do idioma, certo?

No Dot Net é tão simples quanto isto:

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

Agora x é sua resposta. Mas este é o HEX by HEX convert e a conversão de frase em frase é um trabalho para pesquisadores: P

Suman Kr. Nath
fonte
questão é de fato para java. Não vejo como a resposta do .NET está relacionada aqui.
eis