การสร้างอักขระ Unicode จากหมายเลข


114

ฉันต้องการแสดงอักขระ Unicode ใน Java ถ้าฉันทำเช่นนี้มันก็ใช้ได้ดี:

String symbol = "\u2202";

สัญลักษณ์เท่ากับ "∂" นั่นคือสิ่งที่ฉันต้องการ.

ปัญหาคือฉันรู้หมายเลข Unicode และจำเป็นต้องสร้างสัญลักษณ์ Unicode จากสิ่งนั้น ฉันพยายาม (กับฉัน) สิ่งที่ชัดเจน:

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

อย่างไรก็ตามในกรณีนี้สัญลักษณ์จะเท่ากับ "\ u2202" นั่นไม่ใช่สิ่งที่ฉันต้องการ

ฉันจะสร้างสัญลักษณ์ได้อย่างไรถ้าฉันรู้หมายเลข Unicode ของมัน (แต่เฉพาะในขณะทำงานเท่านั้น - ฉันไม่สามารถฮาร์ดโค้ดได้เหมือนตัวอย่างแรก)


1
ลบแบ็กสแลชตัวแรกออกเพื่อที่แทนที่จะหนีแบ็กสแลชมันจะหนีลำดับ Unicode การใช้ "\\" บอก Java ว่าคุณต้องการพิมพ์ "\" ไม่ใช่ใช้เป็นลำดับการหลีกเลี่ยงสำหรับอักขระ Unicode หากคุณลบอันแรกมันจะออกจากลำดับ Unicode แทนไม่ใช่แบ็กสแลชที่สอง อย่างน้อยที่สุดก็จะทำให้ดีที่สุดจากความรู้ของฉัน
คดีของ Fund Monica

คำตอบ:


73

เพียงแค่ส่งของคุณintไปที่ไฟล์char. คุณสามารถแปลงเป็นการStringใช้Character.toString():

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

แก้ไข:

เพียงจำไว้ว่าลำดับหนีในโค้ด Java (คน\uบิต) อยู่ใน HEX int c = 0x2202ดังนั้นถ้าคุณกำลังพยายามที่จะทำซ้ำลำดับหนีคุณจะต้องสิ่งที่ต้องการ


3
แค่ให้กล่องสี่เหลี่ยมแก่ฉัน me มันไม่ให้ฉัน "∂"
Paul Reiners

19
อันตราย Will Robinson! อย่าลืมว่าจุดรหัส Unicode จะไม่จำเป็นต้องพอดีกับถ่าน ดังนั้นคุณต้องแน่ใจล่วงหน้าอย่างแน่นอนว่าค่าของคุณcน้อยกว่า 0x10000 ไม่เช่นนั้นวิธีนี้จะพังอย่างน่ากลัว
David Given

1
@NickHartley ขออภัยไม่ปฏิบัติตาม --- คุณอ่านผิด 0x10000 สำหรับ 10,000 หรือไม่
David Given

10
นั่นเป็นเหตุผลที่ฉันพูดว่า 'ด้านล่าง'! และฉันต้องเน้นว่าแม้ว่าตัวอักษร Java จะสูงถึง 0xffff เท่านั้น แต่คะแนนรหัส Unicode ก็สูงถึง 0xfffff มาตรฐาน Unicode มีการเปลี่ยนแปลงหลังจากออกแบบ Java ทุกวันนี้อักขระ Java ถือคำ UTF-16 ในทางเทคนิคไม่ใช่จุดรหัส Unicode และการลืมสิ่งนี้จะทำให้เกิดความแตกแยกที่น่ากลัวเมื่อแอปพลิเคชันของคุณพบสคริปต์ที่แปลกใหม่
David Given

3
@DavidG ได้รับขอบคุณสำหรับJava chars go up to 0xFFFF. ผมไม่ทราบว่า.
Tony Ennis

128

หากคุณต้องการรับหน่วยรหัสที่เข้ารหัส UTF-16 เป็น a charคุณสามารถแยกวิเคราะห์จำนวนเต็มและส่งไปตามที่ผู้อื่นแนะนำได้

Character.toChars(int)หากคุณต้องการที่จะสนับสนุนจุดรหัสทุกการใช้งาน สิ่งนี้จะจัดการกรณีที่จุดรหัสไม่สามารถใส่ในcharค่าเดียวได้

Doc พูดว่า:

แปลงอักขระที่ระบุ (จุดรหัส Unicode) เป็นการแสดง UTF-16 ที่เก็บไว้ในอาร์เรย์ถ่าน ถ้าจุดรหัสที่ระบุเป็นค่า BMP (Basic Multilingual Plane หรือ Plane 0) อาร์เรย์ถ่านที่ได้จะมีค่าเหมือนกับ codePoint หากจุดรหัสที่ระบุเป็นจุดรหัสเสริมอาร์เรย์ถ่านผลลัพธ์จะมีคู่ตัวแทนที่สอดคล้องกัน


แม้ว่านี่จะเป็นวิธีแก้ปัญหาทั่วไปและในหลาย ๆ กรณีคุณควรใช้สิ่งนี้กับคำตอบที่ยอมรับ แต่คำตอบที่ได้รับการยอมรับนั้นใกล้เคียงกับปัญหาเฉพาะที่ Paul ถาม
Jochem Kuijpers

2
ประการแรกขอบคุณ! ใน Scala ฉันยังไม่สามารถแยกวิเคราะห์อักขระที่มีขนาดใหญ่กว่าไฟล์char. scala> "👨‍🎨".map(_.toInt).flatMap((i: Int) => Character.toChars(i)).map(_.toHexString)จะช่วยให้res11: scala.collection.immutable.IndexedSeq[String] = Vector(f468, 200d, f3a8) อีโมจินี้ "นักร้องชาย" อยู่ที่อยู่กับสามจุดรหัสU+1f468, และU+200d U+1f3a8ไม่มีตัวเลขที่สำคัญที่สุด ฉันสามารถเพิ่มด้วยบิตหรือ ( stackoverflow.com/a/2220476/1007926 ) แต่ไม่รู้วิธีพิจารณาว่าอักขระที่แยกวิเคราะห์ใดถูกตัดทอน ขอบคุณ!
Peter Becich

1
@JochemKuijpers ผมไม่เห็นว่า"คำตอบที่ได้รับการยอมรับเป็นคู่ที่ใกล้ชิดกับปัญหาที่เฉพาะเจาะจง" OP ถามอย่างชัดเจนว่า"ฉันจะสร้างสัญลักษณ์ได้อย่างไรถ้าฉันรู้หมายเลข Unicode ... ?" และคำตอบที่ยอมรับจะใช้ไม่ได้หาก"หมายเลข Unicode"นั้นอยู่นอก BMP ตัวอย่างเช่นคำตอบที่ยอมรับจะล้มเหลวสำหรับจุดรหัส 0x1040C ที่ถูกต้องเนื่องจากอยู่ใน SMP เป็นคำตอบที่ไม่ดีและควรแก้ไขหรือลบทิ้ง
skomisa

สถานการณ์ @skomisa OPs ถูก จำกัด ไว้ที่การแสดงลำดับเลขฐานสิบหก Unicode Escape หากคุณมีอักขระที่ควรเข้ารหัสเป็นคู่ตัวแทนสิ่งนั้นจะสะท้อนให้เห็นในลำดับการหลบหนีเหล่านี้ดังนั้นจึงยังคงใช้งานได้ในตอนท้าย ดังที่ฉันได้กล่าวไปแล้วนี่เป็นวิธีแก้ปัญหาทั่วไปและคุณควรใช้สิ่งนี้
Jochem Kuijpers

20

คำตอบอื่น ๆ ที่นี่สนับสนุนเฉพาะ Unicode ถึง U + FFFF เท่านั้น (คำตอบที่เกี่ยวข้องกับถ่านเพียงอินสแตนซ์เดียว) หรือไม่ได้บอกวิธีไปที่สัญลักษณ์จริง (คำตอบหยุดที่ Character.toChars () หรือใช้วิธีการที่ไม่ถูกต้อง หลังจากนั้น) ดังนั้นการเพิ่มคำตอบของฉันที่นี่ด้วย

เพื่อรองรับจุดรหัสเสริมด้วยนี่คือสิ่งที่ต้องทำ:

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

ฉันยังได้ทำการทดสอบอย่างรวดเร็วด้วยว่าวิธีการแปลงใดใช้ได้ผลและไม่ได้ผล

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

ทำไมมันถึงใช้เป็นซับเดียวไม่ได้? new String(Character.toChars(121849));หยุดพักในคอนโซล Eclipse แต่เวอร์ชันสามบรรทัดใช้งานได้
Noumenon

@Noumenon ไม่สามารถทำให้เกิดปัญหาซ้ำได้ แต่ทำงานได้ดีพอ ๆ กันสำหรับฉัน
eis

ความรุ่งโรจน์เพื่อไปต่อ สำหรับstr4งานมอบหมายไม่ควรcodeเป็นcodePointแทน?
skomisa

6

โปรดจำไว้ว่าcharเป็นชนิดอินทิกรัลดังนั้นจึงสามารถกำหนดค่าจำนวนเต็มได้เช่นเดียวกับค่าคงที่ถ่าน

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

แค่ให้กล่องสี่เหลี่ยมแก่ฉัน me มันไม่ให้ฉัน "∂"
Paul Reiners

3
นั่นเป็นเพราะ 2202 ไม่ใช่สิ่งที่intคุณกำลังมองหา คุณกำลังมองหา 0x2202 ความผิดของฉัน. ไม่ว่าในกรณีใดก็ตามหากคุณมีintจุดรหัสที่คุณต้องการคุณสามารถส่งไปที่ a charและใช้มัน (เพื่อสร้างจุดStringถ้าคุณต้องการ)
ILMTitan

6

อันนี้ใช้ได้ดีสำหรับฉัน

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

ตอนนี้ text2 จะมี∂


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
แม้ว่าโพสต์นี้อาจตอบคำถามได้ แต่จำเป็นต้องมีคำอธิบายว่าคุณกำลังทำอะไรอยู่ เพื่อปรับปรุงคุณภาพและความสามารถในการอ่านคำตอบของคุณ
Ajil O.

1
ขอบคุณมันช่วยฉันได้จริงๆ! ใช้งานได้ดีและง่ายกว่าโซลูชันอื่น ๆ ที่นี่ (จริงๆแล้วคน Java ชอบทำสิ่งที่ซับซ้อนมากเกินไป)
พาร์เซกเกอร์

2

นี่คือวิธีที่คุณทำ:

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

โซลูชันนี้จัดทำโดย Arne Vajhøj


คุณกำลังบอกว่ามันได้ผล? ถ้าเป็นเช่นนั้นจะได้ผลเพราะคุณกำลังตีความสองพันสองร้อยและสองใหม่เป็น 0x2202 ซึ่งแน่นอนว่าไม่ใช่สิ่งเดียวกันเลย
dty

4
โอ้ไม่รอ! ค่า Unicode (ลำดับการหลีกเลี่ยงในซอร์ส Java) เป็นฐานสิบหก! นี่ก็ถูกแล้ว คุณทำให้ทุกคนเข้าใจผิดด้วยการพูดint c = 2202ซึ่งผิด! ทางออกที่ดีกว่านี้พูดง่ายๆint c = 0x2202ซึ่งจะช่วยให้คุณประหยัดผ่าน String ฯลฯ
dty

3
1 @dty: อย่างมีการเรียกร้องให้กลางไม่มีchar ccc...เส้น แค่ใช้int cc = 0x2202;แล้วfinal String text=String.valueOf(cc);
Andrew Coonce

2

แม้ว่านี่จะเป็นคำถามเก่า แต่ก็มีวิธีที่ง่ายมากในการทำเช่นนี้ใน Java 11 ซึ่งเปิดตัวในวันนี้: คุณสามารถใช้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

เนื่องจากวิธีนี้รองรับจุดรหัส Unicode ใด ๆ ความยาวของ String ที่ส่งคืนจึงไม่จำเป็นต้องเป็น 1

รหัสที่จำเป็นสำหรับตัวอย่างที่ระบุในคำถามคือ:

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

แนวทางนี้มีข้อดีหลายประการ:

  • ใช้งานได้กับจุดรหัส Unicode ใด ๆ แทนที่จะเป็นเพียงจุดที่สามารถจัดการได้โดยใช้ไฟล์char.
  • มีความกระชับและเข้าใจได้ง่ายว่าโค้ดกำลังทำอะไรอยู่
  • ส่งคืนค่าเป็นสตริงแทนที่จะเป็น a char[]ซึ่งมักเป็นสิ่งที่คุณต้องการ คำตอบโพสต์โดย McDowellchar[]มีความเหมาะสมถ้าคุณต้องการจุดรหัสกลับมาเป็น

คำชี้แจงเพิ่มเติมเกี่ยวกับคำตอบนี้เนื่องจากคำตอบนี้ทำให้ฉันเห็นได้ชัดในทันทีว่าจะสร้างตัวแปร codePoint อย่างไร ไวยากรณ์ที่นี่ควรเป็น: int codePoint = 0x2202;จากนั้น: String s = Character.toString(codePoint); // <<< Requires JDK 11 !!! หรือในซับเดียว: System.out.println(Character.toString(0x2202)); // Prints ∂ หวังว่านี่จะช่วยให้คนอื่นใช้คุณลักษณะนี้ของ JDK 11
Loathian

1

โค้ดด้านล่างนี้จะเขียนอักขระ Unicode 4 ตัว (แทนด้วยทศนิยม) สำหรับคำว่า "be" ในภาษาญี่ปุ่น ใช่คำกริยา "be" ในภาษาญี่ปุ่นมี 4 ตัวอักษร! ค่าของอักขระเป็นทศนิยมและถูกอ่านเป็นอาร์เรย์ของ String [] - โดยใช้การแบ่งเช่น หากคุณมี Octal หรือ Hex ให้parseIntใช้ 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

1

นี่คือบล็อกสำหรับพิมพ์ตัวอักษร Unicode ระหว่าง\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();
}

0

โชคไม่ดีที่การลบฟันเฟืองหนึ่งตัวตามที่กล่าวไว้ในความคิดเห็นแรก (newbiedoodle) ไม่ได้นำไปสู่ผลลัพธ์ที่ดี IDE ส่วนใหญ่ (ถ้าไม่ใช่ทั้งหมด) ปัญหาข้อผิดพลาดทางไวยากรณ์ ด้วยเหตุนี้รูปแบบ Java Escaped Unicode จึงต้องการไวยากรณ์ "\ uXXXX" โดยที่ XXXX เป็นเลขฐานสิบหก 4 หลักซึ่งเป็นตัวเลขบังคับ ความพยายามในการพับสตริงนี้จากชิ้นส่วนล้มเหลว แน่นอน "\ u" ไม่เหมือนกับ "\\ u" ไวยากรณ์แรกหมายถึง Escape 'u' ส่วนที่สองหมายถึง Escape backlash (ซึ่งก็คือ backlash) ตามด้วย 'u' เป็นเรื่องแปลกที่ในหน้า Apache มีการนำเสนอยูทิลิตี้ซึ่งทำพฤติกรรมนี้ทุกประการ แต่ในความเป็นจริงมันเป็นหนียูทิลิตี้เลียนแบบ Apache มียูทิลิตี้ของตัวเอง (ฉันไม่ได้ทดสอบ) ซึ่งทำงานนี้ให้คุณ อาจจะยังไม่เป็นเช่นนั้นสิ่งที่คุณต้องการจะมีแต่ยูทิลิตี้1นี้มีแนวทางที่ดีในการแก้ปัญหา ด้วยชุดค่าผสมที่อธิบายไว้ข้างต้น (MeraNaamJoker) วิธีแก้ปัญหาของฉันคือสร้างสตริงเลียนแบบ Escaped จากนั้นแปลงกลับเป็น Unicode (เพื่อหลีกเลี่ยงข้อ จำกัด Escaped Unicode จริง) ฉันใช้มันเพื่อคัดลอกข้อความดังนั้นจึงเป็นไปได้ว่าในวิธีการ uencode จะดีกว่าที่จะใช้ '\\ u' ยกเว้น '\\\\ u' ลองมัน.

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

(คำตอบอยู่ใน DOT NET 4.5 และใน java ต้องมีวิธีการที่คล้ายกัน)

ฉันมาจากรัฐเบงกอลตะวันตกในอินเดีย ตามที่ผมเข้าใจปัญหาของคุณคือ ... คุณต้องการที่จะผลิตคล้ายกับ 'অ' (มันเป็นตัวอักษรในภาษาบังคลาเทศ) ซึ่งมี Unicode 0X0985HEX:

ตอนนี้ถ้าคุณรู้ค่านี้ในแง่ของภาษาของคุณแล้วคุณจะสร้างสัญลักษณ์ Unicode เฉพาะของภาษานั้นได้อย่างไร?

ใน Dot Net ทำได้ง่ายๆดังนี้:

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

ตอนนี้ x คือคำตอบของคุณ แต่นี่คือ HEX โดยการแปลง HEX และการแปลงประโยคเป็นประโยคเป็นผลงานสำหรับนักวิจัย: P


เป็นคำถามสำหรับ java ฉันไม่เห็นว่าคำตอบ. NET เกี่ยวข้องอย่างไรที่นี่
eis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.