1. คำนำ
ในความเป็นจริงตั้งแต่ฉันเริ่มเขียนรหัส Java ฉันได้พบปัญหาที่อ่านไม่ถ้วนและการแปลงรหัสนับไม่ถ้วนเช่นรหัสที่อ่านไม่ออกซึ่งเกิดขึ้นเมื่ออ่านจากไฟล์ข้อความเป็นสตริงรหัสที่อ่านไม่ออกซึ่งเกิดขึ้นเมื่อได้รับพารามิเตอร์การร้องขอ HTTP ในเซิร์ฟเล็ต เมื่อคุณพบพวกเขาคุณสามารถแก้ปัญหาได้สำเร็จโดยการค้นหาพวกเขาดังนั้นคุณจึงไม่มีความเข้าใจในเชิงลึก
จนกระทั่งสองวันที่ผ่านมาเพื่อนร่วมชั้นของฉันได้พูดคุยกับฉันเกี่ยวกับปัญหาการเข้ารหัสไฟล์ Java Source (ปัญหานี้วิเคราะห์ในตัวอย่างสุดท้าย) และเริ่มต้นด้วยปัญหานี้และเริ่มต้นด้วยปัญหา จากนั้นเราก็คุยกันขณะค้นหาข้อมูล มันเป็นช่วงดึกที่ในที่สุดเราก็พบเบาะแสสำคัญในบล็อกแก้ปัญหาทั้งหมดและประโยคที่เราไม่เคยเข้าใจมาก่อนสามารถอธิบายได้อย่างชัดเจน ดังนั้นฉันจึงตัดสินใจใช้บทความนี้เพื่อบันทึกความเข้าใจของฉันเกี่ยวกับปัญหาการเข้ารหัสและผลลัพธ์ของการทดลอง
แนวคิดบางอย่างต่อไปนี้เป็นความเข้าใจของฉันเองตามเงื่อนไขจริง หากมีข้อผิดพลาดใด ๆ โปรดตรวจสอบให้แน่ใจว่าได้แก้ไข
2. แนวคิดสรุป
ในวันแรก ๆ อินเทอร์เน็ตยังไม่ได้พัฒนาและคอมพิวเตอร์ถูกใช้เพื่อประมวลผลข้อมูลท้องถิ่นบางแห่งเท่านั้นประเทศและภูมิภาคที่ออกแบบมาหลายรูปแบบสำหรับภาษาท้องถิ่น การเข้ารหัสที่เกี่ยวข้องกับภูมิภาคนี้เรียกว่าการเข้ารหัส ANSI (เพราะเป็นส่วนขยายไปยังรหัส ANSI-ASCII) อย่างไรก็ตามพวกเขาไม่ได้หารือล่วงหน้าว่าจะเข้ากันได้อย่างไร แต่แทนที่จะทำเองซึ่งวางรากฐานของการเข้ารหัสความขัดแย้ง ตัวอย่างเช่นการเข้ารหัส GB2312 ที่ใช้ในความขัดแย้งแผ่นดินใหญ่กับการเข้ารหัส BIG5 ที่ใช้ในไต้หวัน สองไบต์เดียวกันแสดงถึงอักขระที่แตกต่างกันในสองรูปแบบการเข้ารหัส ด้วยการเพิ่มขึ้นของอินเทอร์เน็ตเอกสารมักจะมีหลายภาษาและคอมพิวเตอร์พบปัญหาเมื่อแสดงเพราะไม่ทราบว่าการเข้ารหัสสองไบต์นี้เป็นของ
ปัญหาดังกล่าวเป็นเรื่องธรรมดาในโลกดังนั้นจึงเรียกร้องให้มีการกำหนดชุดอักขระทั่วไปและการกำหนดจำนวนอักขระทั้งหมดในโลกใหม่กำลังเพิ่มขึ้น
เป็นผลให้รหัส Unicode เกิดขึ้นมันมีจำนวนอักขระทั้งหมดในโลกอย่างสม่ำเสมอ เนื่องจากมันสามารถระบุตัวละครได้อย่างไม่ซ้ำกันตัวอักษรจึงต้องได้รับการออกแบบสำหรับรหัส Unicode อย่างไรก็ตามมาตรฐาน Unicode กำหนดชุดอักขระ แต่ไม่ได้ระบุรูปแบบการเข้ารหัสนั่นคือมันจะกำหนดหมายเลขนามธรรมและอักขระที่สอดคล้องกันเท่านั้น แต่ไม่ได้ระบุวิธีการจัดเก็บสตริงของหมายเลข Unicode ข้อกำหนดที่แท้จริงคือวิธีการจัดเก็บ UTF-8, UTF-16, UTF-32 และโซลูชั่นอื่น ๆ ดังนั้นการเข้ารหัสด้วยการเริ่มต้น UTF สามารถแปลงโดยตรงผ่านการคำนวณและค่า Unicode (codepoints, จุดรหัส) ตามชื่อแนะนำ UTF-8 คือการเข้ารหัสความยาว 8 บิตซึ่งเป็นการเข้ารหัสความยาวตัวแปรโดยใช้ 1 ถึง 6 ไบต์เพื่อเข้ารหัสอักขระ (เพราะมันถูก จำกัด โดยช่วง Unicode มันเป็นเพียง 4 ไบต์มากที่สุด); UTF-16 คือการเข้ารหัสหน่วยพื้นฐาน 16 บิตซึ่งเป็นการเข้ารหัสความยาวตัวแปรทั้ง 2 ไบต์หรือ 4 ไบต์ UTF-32 เป็นความยาวคงที่และคงที่ 4 ไบต์เก็บหมายเลข Unicode
ที่จริงแล้วฉันมักจะเข้าใจผิดเกี่ยวกับ Unicode มาก่อน ในความประทับใจของฉันรหัส Unicode สามารถเข้าถึง 0xFFFF ซึ่งหมายความว่ามันสามารถแสดงได้มากถึง 2^16 อักขระเท่านั้น หลังจากอ่านวิกิพีเดียอย่างรอบคอบฉันรู้ว่าโครงการเข้ารหัส UCS-2 ยุคแรกนั้นเป็นแบบนี้ UCS-2 ใช้สองไบต์เพื่อเข้ารหัสอักขระดังนั้นจึงสามารถเข้ารหัสอักขระภายในช่วงของ BMP (ระนาบหลายภาษาพื้นฐานนั่นคือ 0x0000-0xffff ซึ่งมีอักขระที่ใช้กันมากที่สุดในโลก) เพื่อเข้ารหัสอักขระที่มี Unicode มากกว่า 0xFFFF ผู้คนได้ขยายการเข้ารหัส UCS-2 และสร้างการเข้ารหัส UTF-16 ซึ่งเป็นความยาวตัวแปร ในช่วง BMP UTF-16 นั้นเหมือนกับ UCS-2 ในขณะที่ UTF-16 นอก BMP ใช้ 4 ไบต์เพื่อจัดเก็บ
เพื่ออำนวยความสะดวกในคำอธิบายด้านล่างให้ฉันอธิบายแนวคิดของหน่วยรหัส (codeunit) องค์ประกอบพื้นฐานของการเข้ารหัสบางอย่างเรียกว่าหน่วยรหัส ตัวอย่างเช่นหน่วยรหัสของ UTF-8 คือ 1 ไบต์และหน่วยรหัสของ UTF-16 คือ 2 ไบต์ เป็นการยากที่จะอธิบาย แต่เข้าใจง่าย
เพื่อให้เข้ากันได้กับภาษาต่าง ๆ และข้ามแพลตฟอร์มที่ดีขึ้น Javastring จะบันทึกรหัส Unicode สำหรับอักขระ มันใช้ในการใช้รูปแบบการเข้ารหัส UCS-2 เพื่อจัดเก็บ Unicode ต่อมาพบว่าตัวละครในช่วง BMP ไม่เพียงพอ แต่สำหรับการใช้หน่วยความจำและการพิจารณาความเข้ากันได้มันไม่ได้เพิ่มขึ้นเป็น UCS-4 (เช่น UTF-32, แก้ไขการเข้ารหัส 4 ไบต์) แต่ใช้ UTF-16 ที่กล่าวถึงข้างต้น ประเภทถ่านถือได้ว่าเป็นหน่วยรหัส การปฏิบัตินี้ทำให้เกิดปัญหา หากอักขระทั้งหมดอยู่ในช่วง BMP ก็ไม่เป็นไร หากมีอักขระนอก BMP จะไม่เป็นหน่วยรหัสที่สอดคล้องกับอักขระอีกต่อไป วิธีความยาวส่งคืนจำนวนหน่วยรหัสไม่ใช่จำนวนอักขระ วิธีการของ Charat ส่งคืนหน่วยรหัสแทนตัวละครซึ่งจะกลายเป็นปัญหาเมื่อข้ามไป แม้ว่าจะมีวิธีการดำเนินการใหม่บางอย่าง แต่ก็ยังไม่สะดวกและไม่สามารถเข้าถึงได้แบบสุ่ม
นอกจากนี้ฉันพบว่า Java ไม่ได้ประมวลผลตัวอักษร Unicode ที่มีขนาดใหญ่กว่า 0xFFFF เมื่อรวบรวมดังนั้นหากคุณไม่สามารถพิมพ์อักขระที่ไม่ใช่ BMP ได้ แต่คุณรู้ว่ารหัส Unicode ของมันคุณต้องใช้วิธีที่ค่อนข้างโง่เพื่อให้สตริงเก็บไว้ด้วยตนเอง รหัสตัวอย่างมีดังนี้
โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// string str = ""; // เราต้องการกำหนดอักขระดังกล่าวโดยสมมติว่าวิธีการป้อนข้อมูลของฉันไม่สามารถพิมพ์ได้ // แต่ฉันรู้ว่า unicode ของมันคือ 0x1d11e // string str = "/u1d11e"; // สิ่งนี้จะไม่ได้รับการยอมรับ // ดังนั้นจึงสามารถคำนวณได้ผ่านการเข้ารหัส UTF-16 D834 DD1ESTRING STR = "/UD834/UDD1E"; // จากนั้นเขียน System.out.println (str);Notepad ที่มาพร้อมกับ Windows สามารถบันทึกเป็นการเข้ารหัส Unicode ซึ่งหมายถึงการเข้ารหัส UTF-16 ดังที่ได้กล่าวไว้ข้างต้นการเข้ารหัสอักขระหลักที่ใช้ทั้งหมดอยู่ในช่วง BMP และภายในช่วง BMP ค่าการเข้ารหัส UTF-16 ของแต่ละอักขระจะเท่ากับค่า Unicode ที่สอดคล้องกันซึ่งอาจเป็นสาเหตุที่ Microsoft เรียกมันว่า unicode ตัวอย่างเช่นฉันป้อนอักขระ "Good A" สองตัวใน Notepad จากนั้นบันทึกเป็น Unicode Big Endian (ลำดับความสำคัญสูง) และเปิดไฟล์ด้วย Winhex เนื้อหาดังแสดงในรูปด้านล่าง สองไบต์แรกของไฟล์เรียกว่าเครื่องหมายคำสั่งซื้อไบต์ (เครื่องหมายคำสั่งไบต์), (Fe ff) ทำเครื่องหมายคำสั่ง endian เป็นลำดับความสำคัญสูงและจากนั้น (59 7d) คือรหัส Unicode "ดี" และ (00 61) คือรหัส "A"
ด้วยรหัส Unicode ปัญหาไม่สามารถแก้ไขได้ทันทีเนื่องจากก่อนอื่นมีข้อมูลการเข้ารหัสมาตรฐานที่ไม่ใช่ Unicode จำนวนมากในโลกและเป็นไปไม่ได้ที่เราจะทิ้งพวกเขา ประการที่สองการเข้ารหัส Unicode มักใช้พื้นที่มากกว่าการเข้ารหัส ANSI ดังนั้นจากมุมมองของการประหยัดทรัพยากรการเข้ารหัส ANSI ยังคงจำเป็น ดังนั้นจึงจำเป็นต้องสร้างกลไกการแปลงเพื่อให้การเข้ารหัส ANSI สามารถแปลงเป็น Unicode สำหรับการประมวลผลแบบครบวงจรหรือ Unicode สามารถแปลงเป็นการเข้ารหัส ANSI เพื่อตอบสนองความต้องการของแพลตฟอร์ม
วิธีการแปลงค่อนข้างง่ายที่จะพูด สำหรับซีรี่ส์ UTF หรือ ISO-8859-1 การเข้ารหัสที่เข้ากันได้สามารถแปลงโดยตรงผ่านการคำนวณและค่า Unicode (อันที่จริงมันอาจเป็นการค้นหาตาราง) สำหรับการเข้ารหัส ANSI ที่เหลือจากระบบมันสามารถทำได้โดยการค้นหาตาราง Microsoft เรียก CodePage ตารางการแมปนี้ (หน้ารหัส) และจัดประเภทและกำหนดหมายเลขโดยการเข้ารหัส ตัวอย่างเช่น CP936 ทั่วไปของเราคือหน้ารหัส GBK และ CP65001 คือหน้ารหัส UTF-8 รูปต่อไปนี้คือตารางการแมป GBK-> Unicode ที่พบในเว็บไซต์ทางการของ Microsoft (ไม่สมบูรณ์ทางสายตา) ในทำนองเดียวกันควรมีตารางการแมป unicode-> GBK
ด้วยหน้ารหัสคุณสามารถทำการแปลงการเข้ารหัสต่างๆได้อย่างง่ายดาย ตัวอย่างเช่นการแปลงจาก GBK เป็น UTF-8 คุณจะต้องหารข้อมูลด้วยอักขระตามกฎการเข้ารหัส GBK ใช้ข้อมูลที่เข้ารหัสของอักขระแต่ละตัวเพื่อตรวจสอบหน้ารหัส GBK รับค่า Unicode จากนั้นใช้ UNICODE เพื่อตรวจสอบรหัส UTF-8 (หรือคำนวณโดยตรง) เช่นเดียวกันกับวิธีอื่น ๆ หมายเหตุ: UTF-8 เป็นการใช้งานมาตรฐานของ Unicode หน้ารหัสของมันมีค่า Unicode ทั้งหมดดังนั้นการเข้ารหัสใด ๆ จะถูกแปลงเป็น UTF-8 จากนั้นแปลงกลับจะไม่หายไป ณ จุดนี้เราสามารถสรุปได้ว่าเพื่อให้งานแปลงการเข้ารหัสเสร็จสิ้นสิ่งที่สำคัญที่สุดคือการแปลงเป็น Unicode สำเร็จดังนั้นการเลือกชุดอักขระอย่างถูกต้อง (หน้ารหัส) เป็นคีย์
หลังจากทำความเข้าใจกับธรรมชาติของปัญหาการสูญเสียการแปลงรหัสฉันก็เข้าใจทันทีว่าทำไมกรอบ JSP ใช้ ISO-8859-1 เพื่อถอดรหัสพารามิเตอร์การร้องขอ HTTP ซึ่งนำไปสู่ความจริงที่ว่าเราต้องเขียนข้อความดังกล่าวเมื่อเราได้พารามิเตอร์จีน:
Stringparam=newString(s.getBytes("iso-8859-1"),"UTF-8");
เนื่องจากเฟรมเวิร์ก JSP ได้รับกระแสไบนารีไบต์ที่เข้ารหัสโดยพารามิเตอร์จึงไม่ทราบว่าการเข้ารหัสคืออะไร (หรือไม่สนใจ) และไม่ทราบว่าหน้ารหัสใดที่จะตรวจสอบเพื่อแปลงเป็น Unicode จากนั้นมันเลือกวิธีแก้ปัญหาที่จะไม่ทำให้เกิดการสูญเสีย สันนิษฐานว่านี่คือข้อมูลที่เข้ารหัสโดย ISO-8859-1 จากนั้นค้นหาหน้ารหัส ISO-8859-1 เพื่อรับลำดับ Unicode เนื่องจาก ISO-8859-1 ถูกเข้ารหัสโดยไบต์และแตกต่างจาก ASCII จึงเข้ารหัสทุกบิตของพื้นที่ 0 ~ 255 ดังนั้นไบต์ใด ๆ จึงสามารถพบได้ในหน้ารหัส หากมันถูกเปลี่ยนจาก Unicode เป็นสตรีมไบต์ดั้งเดิมจะไม่มีการสูญเสีย ด้วยวิธีนี้สำหรับโปรแกรมเมอร์ยุโรปและอเมริกันที่ไม่ได้พิจารณาภาษาอื่น ๆ พวกเขาสามารถถอดรหัสสตริงได้โดยตรงด้วยกรอบ JSP หากพวกเขาต้องการเข้ากันได้กับภาษาอื่น ๆ พวกเขาจะต้องกลับไปที่สตรีมไบต์ดั้งเดิมและถอดรหัสด้วยหน้ารหัสจริง
ฉันได้อธิบายแนวคิดที่เกี่ยวข้องของ Unicode และการเข้ารหัสอักขระเสร็จแล้ว ต่อไปฉันจะใช้ตัวอย่าง Java เพื่อสัมผัสกับมัน
iii. การวิเคราะห์ตัวอย่าง
1. แปลงเป็นตัวสร้าง unicode-string
วิธีการสร้างสตริงคือการแปลงข้อมูลที่เข้ารหัสต่าง ๆ เป็นลำดับ Unicode (เก็บไว้ในการเข้ารหัส UTF-16) รหัสทดสอบต่อไปนี้ใช้เพื่อแสดงแอปพลิเคชันของวิธีการก่อสร้าง Javastring อักขระที่ไม่ใช่ BMP มีส่วนร่วมในตัวอย่างดังนั้นจึงไม่ได้ใช้วิธีการ codepointat
การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น ioexception {// "hello" gbk ข้อมูลที่เข้ารหัสไบต์ [] gbkdata = {(ไบต์) 0xc4, (ไบต์) 0xe3, (byte) 0xba, (byte) 0xc3}; {(byte) 0xa7, (byte) 0x41, (byte) 0xa6, (byte) 0x6e}; // สร้างสตริงและถอดรหัสเป็น unicodestring strfromgbk = สตริงใหม่ (gbkdata, "gbk"); Showunicode (Strfromgbk); showunicode (strfrombig5);} โมฆะคงที่สาธารณะ showunicode (สตริง str) {สำหรับ (int i = 0; i <str.length (); i ++) {system.out.printf ("// u%x", (int) str.charat (i));} system.out.println ();ผลการดำเนินการมีดังนี้
สามารถพบได้ว่าเนื่องจากรหัส unicode String Masters จึงต้องถูกแปลงเป็นการเข้ารหัสอื่น ๆ !
3. การใช้ Unicode เป็นสะพานเพื่อรับรู้การเข้ารหัสการแปลงร่วมกัน
ด้วยรากฐานของสองส่วนข้างต้นมันเป็นเรื่องง่ายมากที่จะตระหนักถึงการเข้ารหัสและการแปลงร่วมกัน คุณเพียงแค่ต้องใช้มันเข้าด้วยกัน ก่อนอื่น Newstring แปลงข้อมูลที่เข้ารหัสต้นฉบับเป็นลำดับ Unicode จากนั้นเรียก GetBytes เพื่อถ่ายโอนไปยังการเข้ารหัสที่ระบุ
ตัวอย่างเช่นรหัสการแปลง GBK เป็น BIG5 ที่ง่ายมากมีดังนี้
โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น unsupportencodingexception {// สมมติว่านี่คือข้อมูลที่อ่านจากไฟล์ในสตรีมไบต์ (การเข้ารหัส GBK) ไบต์ [] gbkdata = {(byte) 0xc4, (byte) 0xe3, (byte) สตริง (gbkdata, "gbk"); // แปลงจาก Unicode เป็น big5 encoding byte [] big5data = tmp.getBytes ("big5"); // การดำเนินการครั้งที่สอง ... }4. ปัญหาการสูญเสียการเข้ารหัส
ตามที่อธิบายไว้ข้างต้นเหตุผลที่ Framework JSP ใช้ชุดอักขระ ISO-8859-1 ที่ตั้งไว้เพื่อถอดรหัส ก่อนอื่นใช้ตัวอย่างเพื่อจำลองกระบวนการกู้คืนนี้รหัสมีดังนี้
การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น unsupportencodingexception {// jsp framework ได้รับ 6 ไบต์ของข้อมูลไบต์ [] data = {(byte) 0xe4, (byte) 0xbd, (byte) 0xa0 showbytes (data); // jsp framework สันนิษฐานว่ามันคือ ISO-8859-1 การเข้ารหัสสร้างสตริงวัตถุสตริง tmp = สตริงใหม่ (ข้อมูล "iso-8859-1"); // ***************************************************************** ผลการถอดรหัส ISO: " + TMP); // ก่อนอื่นรับข้อมูล 6 ไบต์ดั้งเดิม (ค้นหาหน้ารหัสของ ISO-8859-1) ไบต์ [] utfdata = tmp.getBytes (" iso-8859-1 "); หน้า UTF-8 เพื่อสร้างสตริงสตริงผลลัพธ์ = สตริงใหม่ (utfdata, "UTF-8"); // พิมพ์อีกครั้งมันถูกต้อง! System.out.println ("UTF-8 ผลการถอดรหัส:" + result);} โมฆะคงที่ public showbytes (byte [] data) {สำหรับ (byte b: data) system.out.printf ("0x%x", b); system.out.println ();}}}};ผลการทำงานมีดังนี้ เอาต์พุตแรกไม่ถูกต้องเนื่องจากกฎการถอดรหัสไม่ถูกต้อง ฉันยังตรวจสอบหน้ารหัสไม่ถูกต้องและได้รับ Unicode ผิด จากนั้นฉันก็พบว่าข้อมูลสามารถกู้คืนได้อย่างสมบูรณ์แบบผ่านการตรวจสอบด้านหลัง Unicode ที่ไม่ถูกต้องของหน้ารหัส ISO-8859-1
นี่ไม่ใช่ประเด็น หากกุญแจสำคัญคือการแทนที่ "จีน" ด้วย "จีน" การรวบรวมจะประสบความสำเร็จและผลการดำเนินการดังแสดงในรูปด้านล่าง นอกจากนี้ยังสามารถพบได้เพิ่มเติมว่าเมื่อจำนวนอักขระจีนเป็นคี่การรวบรวมล้มเหลวและเมื่อจำนวนนั้นเป็นไปได้ก็จะผ่านไป ทำไมถึงเป็นเช่นนี้? มาวิเคราะห์โดยละเอียดด้านล่าง
เนื่องจาก Javastring ใช้ Unicode ภายในคอมไพเลอร์จะแปลงรหัสตัวอักษรสตริงของเราในระหว่างการรวบรวมและแปลงจากการเข้ารหัสไฟล์ต้นฉบับเป็น Unicode (Wikipedia บอกว่าใช้การเข้ารหัสที่แตกต่างกันเล็กน้อยจาก UTF-8) เมื่อรวบรวมเราไม่ได้ระบุพารามิเตอร์การเข้ารหัสดังนั้นคอมไพเลอร์จะถอดรหัสใน GBK โดยค่าเริ่มต้น หากคุณมีความรู้เกี่ยวกับ UTF-8 และ GBK คุณควรรู้ว่าโดยทั่วไปแล้วตัวละครจีนต้องการ 3 ไบต์เพื่อใช้การเข้ารหัส UTF-8 ในขณะที่ GBK ต้องการเพียง 2 ไบต์ สิ่งนี้สามารถอธิบายได้ว่าทำไมความเท่าเทียมกันของหมายเลขอักขระจะส่งผลกระทบต่อผลลัพธ์เนื่องจากหากมี 2 ตัวอักษรการเข้ารหัส UTF-8 จะใช้ 6 ไบต์และการถอดรหัสใน GBK สามารถถอดรหัสได้ 3 อักขระ หากเป็นตัวละคร 1 ตัวจะมีไบต์ที่ไม่สามารถใช้งานได้ซึ่งเป็นสถานที่ที่เครื่องหมายคำถามในรูป
เพื่อให้มีความเฉพาะเจาะจงมากขึ้นการเข้ารหัส UTF-8 ของคำว่า "จีน" ในไฟล์ต้นฉบับคือ E4B8ADE59BBD คอมไพเลอร์ถอดรหัสใน GBK คู่ 3 ไบต์ค้นหา CP936 เพื่อรับ 3 ค่า Unicode ซึ่งคือ 6d93e15e6d57 ตามลำดับซึ่งสอดคล้องกับอักขระแปลก ๆ สามตัวในกราฟผลลัพธ์ ดังที่แสดงในรูปด้านล่างหลังจากการรวบรวม Unicodes ทั้งสามนี้จะถูกเก็บไว้ในการเข้ารหัส UTF-8-like ในไฟล์. class เมื่อทำงาน Unicode จะถูกเก็บไว้ใน JVM อย่างไรก็ตามเมื่อเอาต์พุตสุดท้ายคือเอาต์พุตมันจะยังคงถูกเข้ารหัสและส่งผ่านไปยังเทอร์มินัล การเข้ารหัสที่ตกลงกันในครั้งนี้คือการเข้ารหัสที่กำหนดโดยพื้นที่ระบบดังนั้นหากการตั้งค่าการเข้ารหัสเทอร์มินัลเปลี่ยนไปมันจะยังคงอ่านไม่ออก E15E ของเราที่นี่ไม่ได้กำหนดอักขระที่เกี่ยวข้องในมาตรฐาน Unicode ดังนั้นจอแสดงผลจะแตกต่างกันภายใต้ฟอนต์ที่แตกต่างกันบนแพลตฟอร์มที่แตกต่างกัน
สามารถจินตนาการได้ว่าหากไฟล์ต้นฉบับถูกเก็บไว้ในการเข้ารหัส GBK จากนั้นหลอกให้คอมไพเลอร์บอกว่ามันเป็น UTF-8 มันไม่สามารถรวบรวมและผ่านได้ไม่ว่าจะมีตัวละครจีนจำนวนเท่าใดเพราะการเข้ารหัส UTF-8 เป็นปกติ
แน่นอนวิธีที่ตรงที่สุดในการเปิดใช้งานคอมไพเลอร์เพื่อแปลงการเข้ารหัสเป็น Unicode อย่างถูกต้องคือการบอกคอมไพเลอร์อย่างตรงไปตรงมาว่าการเข้ารหัสไฟล์ต้นฉบับคืออะไร
4. สรุป
หลังจากคอลเลกชันและการทดลองนี้ฉันได้เรียนรู้แนวคิดมากมายที่เกี่ยวข้องกับการเข้ารหัสและคุ้นเคยกับกระบวนการเฉพาะของการแปลงการเข้ารหัส แนวคิดเหล่านี้สามารถสรุปได้กับภาษาการเขียนโปรแกรมต่างๆและหลักการดำเนินการมีความคล้ายคลึงกัน ดังนั้นฉันคิดว่าฉันจะไม่ไม่รู้ถึงปัญหาแบบนี้อีกต่อไปในอนาคต
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้เกี่ยวกับตัวอย่างแนวคิดการเข้ารหัสเช่น ANSI, Unicode, BMP, UTF ฯลฯ ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!