Tạo ký tự Unicode từ số của nó


114

Tôi muốn hiển thị một ký tự Unicode trong Java. Nếu tôi làm điều này, nó hoạt động tốt:

String symbol = "\u2202";

ký hiệu bằng "∂". Đó là điều tôi muốn.

Vấn đề là tôi biết số Unicode và cần tạo ký hiệu Unicode từ đó. Tôi đã thử (với tôi) điều hiển nhiên:

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

Tuy nhiên, trong trường hợp này, ký hiệu bằng "\ u2202". Đó không phải là điều tôi muốn.

Làm thế nào tôi có thể xây dựng biểu tượng nếu tôi biết số Unicode của nó (nhưng chỉ tại thời điểm chạy --- Tôi không thể mã hóa nó như ví dụ đầu tiên)?


1
Loại bỏ dấu gạch chéo ngược đầu tiên, để thay vì thoát khỏi dấu gạch chéo ngược, nó sẽ thoát khỏi chuỗi Unicode. Việc sử dụng "\\" cho Java biết rằng bạn muốn in ra "\", không sử dụng nó như là quá khứ của một chuỗi thoát cho các ký tự Unicode. Nếu bạn xóa cái đầu tiên thì thay vào đó nó sẽ thoát khỏi chuỗi Unicode chứ không phải dấu gạch chéo ngược thứ hai. Ít nhất, nó sẽ theo hiểu biết tốt nhất của tôi.
Vụ kiện của Fund Monica

Câu trả lời:


73

Chỉ cần truyền của bạn intđến a char. Bạn có thể chuyển đổi thành Stringsử dụng Character.toString():

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

BIÊN TẬP:

Chỉ cần nhớ rằng các trình tự thoát trong mã nguồn Java (các \ubit) nằm trong HEX, vì vậy nếu bạn đang cố gắng tái tạo trình tự thoát, bạn sẽ cần một cái gì đó như thế int c = 0x2202.


3
Đó chỉ là cho tôi một hộp vuông, ࢚. Nó không cho tôi "∂".
Paul Reiners

19
Nguy hiểm, Will Robinson! Đừng quên rằng các điểm mã Unicode sẽ không nhất thiết phải phù hợp với một ký tự . Vì vậy, bạn cần hoàn toàn chắc chắn trước rằng giá trị của bạn cnhỏ hơn 0x10000, nếu không cách tiếp cận này sẽ phá vỡ một cách khủng khiếp.
David Given

1
@NickHartley Xin lỗi, không theo dõi --- bạn có đọc nhầm 0x10000 cho 10000 không?
David Given

10
Đó là lý do tại sao tôi nói 'bên dưới'! Và tôi cần nhấn mạnh rằng, mặc dù thực tế là các ký tự Java chỉ tăng đến 0xffff, các điểm mã Unicode lên đến 0xfffff. Chuẩn Unicode đã thay đổi sau khi Java được thiết kế. Ngày nay, các ký tự Java về mặt kỹ thuật giữ các từ UTF-16 chứ không phải các điểm mã Unicode, và việc quên điều này sẽ gây ra sự cố đáng ghét khi ứng dụng của bạn gặp phải một tập lệnh lạ.
David Given

3
@DavidGiven cảm ơn vì Java chars go up to 0xFFFF. Tôi không biết điều đó.
Tony Ennis

128

Nếu bạn muốn nhận đơn vị mã được mã hóa UTF-16 dưới dạng char , bạn có thể phân tích cú pháp số nguyên và truyền sang nó như những người khác đã đề xuất.

Nếu bạn muốn hỗ trợ tất cả các điểm mã, hãy sử dụng Character.toChars(int). Điều này sẽ xử lý các trường hợp mà các điểm mã không thể nằm trong một chargiá trị duy nhất .

Doc nói:

Chuyển đổi ký tự được chỉ định (điểm mã Unicode) thành biểu diễn UTF-16 của nó được lưu trữ trong một mảng char. Nếu điểm mã được chỉ định là giá trị BMP (Mặt phẳng đa ngôn ngữ cơ bản hoặc Mặt phẳng 0), mảng char kết quả có cùng giá trị với codePoint. Nếu điểm mã được chỉ định là điểm mã bổ sung, mảng char kết quả có cặp thay thế tương ứng.


Mặc dù đây là một giải pháp tổng quát hơn và trong nhiều trường hợp, bạn nên sử dụng nó thay cho câu trả lời được chấp nhận, câu trả lời được chấp nhận sẽ phù hợp hơn với vấn đề cụ thể mà Paul yêu cầu.
Jochem Kuijpers

2
Đầu tiên, cảm ơn! Trong Scala, tôi vẫn không thể phân tích cú pháp các ký tự lớn hơn a char. scala> "👨‍🎨".map(_.toInt).flatMap((i: Int) => Character.toChars(i)).map(_.toHexString)cho res11: scala.collection.immutable.IndexedSeq[String] = Vector(f468, 200d, f3a8) biểu tượng cảm xúc này "nam ca sĩ", được giải quyết với ba điểm mã U+1f468, U+200dU+1f3a8. Chữ số có nghĩa nhất bị thiếu. Tôi có thể thêm nó bằng một bitwise HOẶC ( stackoverflow.com/a/2220476/1007926 ), nhưng không biết cách xác định ký tự được phân tích cú pháp nào đã bị cắt bớt. Cảm ơn!
Peter Becich

1
@JochemKuijpers Tôi không đồng ý rằng "câu trả lời được chấp nhận là phù hợp hơn với vấn đề cụ thể" . OP đã hỏi một cách rõ ràng "Làm cách nào để xây dựng biểu tượng nếu tôi biết số Unicode của nó ...?" và câu trả lời được chấp nhận không thể hoạt động nếu "số Unicode" đó nằm ngoài BMP. Ví dụ: câu trả lời được chấp nhận không thành công cho điểm mã hợp lệ 0x1040C vì nó nằm trong SMP. Đó là một câu trả lời kém, và cần được sửa chữa hoặc xóa.
skomisa

Kịch bản @skomisa OPs được giới hạn trong việc biểu diễn chuỗi thoát Unicode thập lục phân. Nếu bạn có một ký tự cần được mã hóa dưới dạng một cặp thay thế, thì ký tự đó được phản ánh trong các chuỗi thoát này, vì vậy cuối cùng nó vẫn hoạt động. Như tôi đã nói, đây là một giải pháp tổng quát hơn và bạn nên sử dụng nó.
Jochem Kuijpers

20

Các câu trả lời khác ở đây hoặc chỉ hỗ trợ unicode tối đa U + FFFF (các câu trả lời chỉ liên quan đến một trường hợp của char) hoặc không cho biết cách truy cập biểu tượng thực tế (các câu trả lời dừng lại ở Character.toChars () hoặc sử dụng phương pháp không chính xác sau đó), vì vậy thêm câu trả lời của tôi ở đây.

Để hỗ trợ điểm mã bổ sung, đây là những gì cần phải làm:

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

Tôi cũng đã thực hiện một bài kiểm tra nhanh xem phương pháp chuyển đổi nào hoạt động và phương pháp nào không

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

Tại sao nó không hoạt động như một lớp lót? new String(Character.toChars(121849));ngắt trong bảng điều khiển Eclipse, nhưng phiên bản ba dòng hoạt động.
Noumenon

@Noumenon không thể tái tạo vấn đề, hoạt động tốt như nhau đối với tôi
eis

Kudo để tiến xa hơn. Đối với str4nhiệm vụ, không codenên codePointthay thế?
skomisa

6

Hãy nhớ rằng đó charlà một kiểu tích phân và do đó có thể được cung cấp một giá trị nguyên, cũng như một hằng số char.

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

Đó chỉ là cho tôi một hộp vuông, ࢚. Nó không cho tôi "∂".
Paul Reiners

3
Đó là bởi vì 2202 không phải là intbạn đang tìm kiếm. Bạn đang tìm kiếm 0x2202. Lỗi của tôi. Trong mọi trường hợp, nếu bạn có intđiểm mã mà bạn đang tìm kiếm, bạn có thể truyền nó đến a charvà sử dụng nó (để tạo a Stringnếu bạn muốn).
ILMTitan

6

Điều này làm việc tốt cho tôi.

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

Bây giờ text2 sẽ có ∂.


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
Mặc dù bài đăng này có thể trả lời câu hỏi, nhưng cần phải giải thích về những gì bạn đang làm; để cải thiện chất lượng và khả năng đọc câu trả lời của bạn
Ajil O.

1
Cảm ơn, nó thực sự đã giúp tôi! Hoạt động tốt và dễ dàng hơn các giải pháp khác ở đây (thực sự, người Java rất thích làm những thứ quá phức tạp).
parsecer

2

Đây là cách bạn làm điều đó:

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

Giải pháp này là của Arne Vajhøj.


Bạn đang nói điều này hoạt động? Nếu vậy, điều này hoạt động bởi vì bạn đang diễn giải lại hai nghìn, hai trăm lẻ hai dưới dạng 0x2202, tất nhiên, điều này không giống nhau chút nào.
dty

4
Ồ, không, chờ đã! Các giá trị Unicode (\ u chuỗi thoát trong nguồn Java) LÀ hex! Vì vậy, điều này là đúng. Bạn chỉ lừa dối mọi người bằng cách nói int c = 2202, đó là sai! Nói một cách đơn giản, giải pháp tốt hơn điều này int c = 0x2202sẽ giúp bạn tiết kiệm khi đi qua Chuỗi, v.v.
dty 07/04

3
+1 @dty: Hoàn toàn không có lời kêu gọi nào cho đường giữa char ccc.... Chỉ cần sử dụng int cc = 0x2202;và sau đófinal String text=String.valueOf(cc);
Andrew Coonce

2

Mặc dù đây là một câu hỏi cũ, nhưng có một cách rất dễ dàng để thực hiện điều này trong Java 11 được phát hành ngày hôm nay: bạn có thể sử dụng một quá tải mới của 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

Vì phương thức này hỗ trợ bất kỳ điểm mã Unicode nào, độ dài của Chuỗi được trả về không nhất thiết phải là 1.

Mã cần thiết cho ví dụ được đưa ra trong câu hỏi chỉ đơn giản là:

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

Cách tiếp cận này mang lại một số lợi thế:

  • Nó hoạt động cho bất kỳ điểm mã Unicode nào hơn là chỉ những điểm có thể được xử lý bằng cách sử dụng a char.
  • Nó ngắn gọn và dễ hiểu những gì mã đang làm.
  • Nó trả về giá trị dưới dạng một chuỗi thay vì a char[], thường là những gì bạn muốn. Câu trả lời được đăng bởi McDowell là phù hợp nếu bạn muốn điểm mã được trả về là char[].

Một số giải thích rõ hơn về câu trả lời này vì câu trả lời này đã giúp tôi thấy rõ ngay cách tạo biến codePoint. Cú pháp ở đây phải là: int codePoint = 0x2202;Sau đó: String s = Character.toString(codePoint); // <<< Requires JDK 11 !!! Hoặc trong một chữ lót: System.out.println(Character.toString(0x2202)); // Prints ∂ Hy vọng điều này sẽ giúp người khác sử dụng tính năng này của JDK 11.
Loathian

1

Đoạn mã dưới đây sẽ viết 4 ký tự unicode (được biểu thị bằng số thập phân) cho từ "be" trong tiếng Nhật. Vâng, động từ "be" trong tiếng Nhật có 4 ký tự! Giá trị của các ký tự ở dạng thập phân và nó đã được đọc vào một mảng Chuỗi [] - chẳng hạn như sử dụng phép tách. Nếu bạn có hệ bát phân hoặc hệ thập lục phân , hãy phân tích cú pháp cũng không cần dùng cơ số.

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

Đây là một khối để in ra các ký tự unicode từ \u00c0đến \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

Thật không may, để loại bỏ một phản ứng dữ dội như đã đề cập trong nhận xét đầu tiên (newbiedoodle) không dẫn đến kết quả tốt. Hầu hết (nếu không phải tất cả) IDE gặp lỗi cú pháp. Lý do là ở chỗ, định dạng Unicode đã thoát khỏi Java yêu cầu cú pháp "\ uXXXX", trong đó XXXX là 4 chữ số thập lục phân, là bắt buộc. Nỗ lực gấp chuỗi này từ các mảnh không thành công. Tất nhiên, "\ u" không giống như "\\ u". Cú pháp đầu tiên có nghĩa là thoát 'u', cú pháp thứ hai có nghĩa là dấu gạch chéo ngược thoát ra (là dấu gạch chéo ngược) theo sau là 'u'. Thật kỳ lạ, trên các trang Apache được trình bày tiện ích, thực hiện chính xác hành vi này. Nhưng trên thực tế, đó là tiện ích bắt chước Escape . Apache có một số tiện ích riêng của nó (tôi đã không thử nghiệm chúng), những tiện ích này sẽ làm việc cho bạn. Có thể là, vẫn là không có, muốn cái gì đều có. 1Nhưng tiện ích nàycó cách tiếp cận giải pháp tốt. Với sự kết hợp được mô tả ở trên (MeraNaamJoker). Giải pháp của tôi là tạo chuỗi bắt chước đã thoát này và sau đó chuyển đổi nó trở lại thành unicode (để tránh hạn chế Unicode đã thoát thực sự). Tôi đã sử dụng nó để sao chép văn bản, vì vậy có thể, trong phương thức uencode sẽ tốt hơn nếu sử dụng '\\ u' ngoại trừ '\\\\ u'. Thử nó.

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

(TRẢ LỜI LÀ TRONG DOT NET 4.5 và trong java, phải tồn tại một cách tiếp cận tương tự)

Tôi đến từ Tây Bengal ở ẤN ĐỘ. Theo tôi hiểu, vấn đề của bạn là ... Bạn muốn viết tương tự với 'অ' (Đây là một chữ cái trong ngôn ngữ Bengali) có Unicode HEX:0X0985 .

Bây giờ nếu bạn biết giá trị này đối với ngôn ngữ của bạn thì bạn sẽ tạo ra ký hiệu Unicode cụ thể cho ngôn ngữ đó như thế nào?

Trong Dot Net nó đơn giản như sau:

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

Bây giờ x là câu trả lời của bạn. Nhưng đây là HEX do HEX chuyển đổi và chuyển đổi câu thành câu là công việc của các nhà nghiên cứu: P


câu hỏi thực sự dành cho java. Tôi không thấy câu trả lời .NET có liên quan như thế nào ở đây.
eis
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.