- UTF-8 เข้ารหัสจุด Unicode ในขนาด 1–4 ไบต์ เข้ากันได้กับ ASCII และใช้ได้กับทุกภาษา
- การซิงโครไนซ์และการตรวจสอบตนเอง: รูปแบบ 0/110/1110/11110 ป้องกันการทับซ้อนและทำให้ตรวจจับข้อผิดพลาดได้ง่ายขึ้น
- เว็บและระบบ: เมตาชาร์เซ็ต การสนับสนุนจำนวนมาก และการแปลงที่ง่ายดายบน Windows/macOS/Linux
หากคุณกำลังอ่านบทความนี้โดยไม่เห็นสัญลักษณ์แปลก ๆ ใด ๆ นั่นเป็นเพราะ UTF-8การเข้ารหัสนี้ช่วยให้ตัวอักษร เครื่องหมายเน้นเสียง สัญลักษณ์ทางเทคนิค และแม้แต่สัญลักษณ์อีโมจิ แสดงผลได้เหมือนกันในเบราว์เซอร์ ระบบปฏิบัติการ หรือโปรแกรมอีเมลสมัยใหม่ทุกชนิดเป็นมาตรฐานที่แพร่หลายที่สุดบนเว็บและเป็นรากฐานของการสื่อสารดิจิทัลอย่างที่เราคุ้นเคยกันดี
เมื่ออุปกรณ์แสดงข้อความ จริงๆ แล้วมันกำลังประมวลผลตัวเลขตัวเลขเหล่านี้คือรหัสจุด (code points) ที่กำหนดโดยมาตรฐาน Unicodeและเพื่อแปลงตัวเลขเหล่านี้ให้เป็นไบต์ที่ส่งผ่านเครือข่ายหรือบันทึกไปยังไฟล์เราจึงทำการแปลง: UTF-8ในบรรทัดต่อไปนี้ คุณจะได้เข้าใจว่ามันคืออะไร ทำงานอย่างไร ทำไมมันถึงกลายเป็นมาตรฐาน ข้อดีและข้อจำกัดของมัน และวิธีหลีกเลี่ยงข้อผิดพลาดทั่วไป
UTF-8 คืออะไร?
UTF-8 (8-bit Unicode Transformation Format) เป็นวิธีการแปลงรหัสอักขระ Unicode ให้เป็นลำดับไบต์คุณสมบัติหลักคือการใช้ความยาวที่แปรผันได้ กล่าวคือ อักขระบางตัวใช้ 1 ไบต์ ในขณะที่บางตัวต้องการ 2, 3 หรือ 4 ไบต์ これによりทำให้สามารถเขียนข้อความขนาดกะทัดรัดด้วยอักขระละตินอย่างง่ายได้แต่ก็สามารถใช้แทนอักขระใดๆ จากชุดอักขระ Unicode ได้เช่นกัน
มันเข้ากันได้กับASCII อย่างสมบูรณ์ : อักขระ 128 ตัวแรก (U+0000 ถึง U+007F) ถูกเข้ารหัสด้วยไบต์เดียวที่เหมือนกับ ASCII 7 บิตซึ่งทำให้การเปลี่ยนจากระบบเก่าเป็นไปได้ง่ายขึ้นและเป็นเหตุผลที่ทำให้ประสบความสำเร็จอย่างมากในอินเทอร์เน็ต อีเมล และโปรโตคอลของ IETF
UTF-8 โดดเด่นในเรื่องความแข็งแกร่ง : มันมีบิตการซิงโครไนซ์ที่ช่วยให้สามารถระบุจุดเริ่มต้นของแต่ละสัญลักษณ์ได้อย่างน่าเชื่อถือ คุณสมบัติการซิงโครไนซ์ด้วยตนเองนี้ทำให้ตรวจจับได้ง่ายว่าลำดับ "ดูเหมือน" UTF-8 หรือไม่ซึ่งมีประโยชน์มากในเครื่องมือและตัวแยกวิเคราะห์
ยูนิโค้ด: รากฐานของทุกสิ่ง
ยูนิโค้ด (Unicode) คือมาตรฐานสากลที่กำหนดหมายเลขเฉพาะให้กับอักขระแต่ละตัวโดยไม่คำนึงถึงภาษา แพลตฟอร์ม หรือแอปพลิเคชัน หมายเลขนี้เรียกว่าโค้ดพอยต์ (code point)และมักเขียนในรูปแบบเลขฐานสิบหกในรูปแบบ U+XXXX (หรือตัวเลขมากกว่านั้นหากจำเป็น)
เช่น อักษรตัวใหญ่ “A” คือ U+0041ใน HTML เราสามารถเรียกมันว่า A. คอมพิวเตอร์ของคุณไม่ได้ "คิด" ว่า A เป็นตัวอักษร แต่เป็นตัวเลข 65จากนั้นการเข้ารหัส (เช่น UTF-8) จะตัดสินใจว่าจะแสดงตัวเลขนั้นเป็นไบต์อย่างไร
หากคุณต้องการดูว่า Unicode แปลงเป็นอักขระบนพีซีของคุณอย่างไรบนระบบปฏิบัติการ Windows คุณสามารถกดปุ่ม Alt ค้างไว้แล้วพิมพ์รหัสตัวเลขทศนิยมบนแป้นพิมพ์ตัวเลขได้ เช่นAlt+65 จะได้ “A” (ดูรายการรหัส Alt ทั้งหมด ) นี่เป็นทางลัดแบบคลาสสิกที่แสดงให้เห็นว่ารหัสเหล่านั้นอยู่เบื้องหลังอักขระที่คุณเห็นอย่างไร
ประวัติย่อ: UTF-8 ถือกำเนิดขึ้นได้อย่างไร
UTF-8 ถูกคิดค้นโดย Ken Thompson ภายใต้การแนะนำของ Rob Pike เมื่อวันที่ 2 กันยายน 1992พวกเขาได้นำไปใช้ในระบบปฏิบัติการ Plan 9 จาก Bell Labsและเปิดตัวอย่างเป็นทางการที่งาน USENIX (ซานดิเอโก มกราคม 1993)ในระหว่างการกำหนดมาตรฐาน ซึ่งได้รับการสนับสนุนโดยX/Open Joint Internationalization Group (XOJIG)นั้นUTF-8 เป็นที่รู้จักกันในชื่อต่างๆ เช่น FSS/UTF และ UTF-2ก่อนที่จะถูกรวมเข้าเป็น UTF-8 ในที่สุด
การออกแบบนี้ได้แก้ไขปัญหาเชิงปฏิบัติที่เคยเป็นอุปสรรคต่อความพยายามในการเข้ารหัสแบบสากลในอดีต ได้แก่ ความเข้ากันได้กับ ASCII การซิงโครไนซ์อัตโนมัติ การไม่มีไบต์ที่ทับซ้อนกัน และความง่ายในการตรวจจับข้อผิดพลาดความสมดุลนี้ทำให้มันกลายเป็นมาตรฐานโดยพฤตินัยของเว็บ
UTF-8 ทำงานอย่างไรภายใต้ประทุน
UTF-8 จัดกลุ่มอักขระตามจำนวนไบต์ที่จำเป็นในการเข้ารหัสจำนวนไบต์ขึ้นอยู่กับจุดรหัสยูนิโค้ดเท่านั้น และเป็นไปตามรูปแบบบิตที่ระบุความยาวของลำดับ
- 1 ไบต์ (U+0000 ถึง U+007F): อักขระ ASCII รูปแบบ:
0xxxxxxxบิตที่สำคัญที่สุดคือ 0 ซึ่ง รับประกันความเข้ากันได้โดยตรงกับ ASCII. - 2 ไบต์ (U+0080 ถึง U+07FF): รูปแบบ
110yyyyy 10xxxxxx. ใช้สำหรับตัวอักษรยุโรปส่วนใหญ่ที่มีเครื่องหมายกำกับเสียงและตัวอักษรอื่นๆ เช่น กรีก ซีริลลิก ฮีบรู หรืออาหรับ. - 3 ไบต์ (U+0800 ถึง U+FFFF): รูปแบบ
1110zzzz 10yyyyyy 10xxxxxx. รวมถึงแผนพื้นฐานหลายภาษา (BMP) พร้อม CJK (จีน ญี่ปุ่น เกาหลี)สัญลักษณ์ทางเทคนิคและอักขระที่ใช้กันทั่วไป - 4 ไบต์ (U+10000 ถึง U+10FFFF): รูปแบบ
11110uuu 10uuzzzz 10yyyyyy 10xxxxxx. แสดงถึงระนาบเสริม: สัญลักษณ์ทางคณิตศาสตร์ขั้นสูง งานเขียนทางประวัติศาสตร์ สัญลักษณ์อุดมคติที่ไม่ค่อยพบเห็นบ่อย ฯลฯ
หัวใจสำคัญของการซิงโครไนซ์อัตโนมัติอยู่ที่บิตส่วนหัว : 0 สำหรับ ASCII; 110 สำหรับสองไบต์; 1110 สำหรับสามไบต์; 11110 สำหรับสี่ไบต์ไบต์ต่อเนื่องจะเริ่มต้นด้วย 10 เสมอด้วยเหตุนี้ไบต์ต่อเนื่องจึงไม่สามารถปรากฏเป็นไบต์เริ่มต้นได้และลำดับที่ถูกต้องจะไม่สามารถเป็นส่วนย่อยของสตริงที่ยาวกว่าได้ (หลักการไม่ทับซ้อน)
ความเทียบเท่ากับ UTF-16 และคู่ตัวแทน
UTF-16 แสดงถึงจุดรหัส BMP ที่มีหน่วย 16 บิต และจุดเหนือ U+FFFF ด้วย คู่ทดแทน อยู่ในช่วง D800–DFFF. แทน, UTF-8 เข้ารหัสจุดรหัสจริงเสมอไม่ใช่หน่วย UTF-16 ซึ่งหลีกเลี่ยงการสับสนกับสิ่งทดแทน
ในอดีต ร่างมาตรฐานบางฉบับอนุญาตให้ใช้5 หรือ 6 ไบต์ใน UTF-8 เพื่อครอบคลุมช่วงที่กว้างขึ้น แต่Unicode และ RFC 3629 จำกัด UTF-8 ไว้ที่สูงสุด 4 ไบต์ ISO/IEC เคยพิจารณาตัวเลือกที่กว้างกว่านี้ แต่ตัวเลือกเหล่านั้นไม่ได้เป็นส่วนหนึ่งของมาตรฐานปัจจุบัน
ตัวอย่างการปฏิบัติ: ñ
อักขระ “ñ” มีจุดรหัส U+00F1ซึ่งอยู่ในช่วงสองไบต์ ตามรูปแบบนี้ จะถูกเข้ารหัสเป็น 110xxxxx 10xxxxxx. การแสดง UTF-8 คือ 0xC3 0xB1การถอดรหัสเป็นกระบวนการย้อนกลับ: การอ่านส่วนที่มีประโยชน์และสร้างจุดรหัสดั้งเดิมขึ้นมาใหม่
ข้อดีและข้อจำกัดของ UTF-8
ข้อดีหลักๆ :
- การรองรับ ASCII:ข้อความ ASCII ถูกต้องในรูปแบบ UTF-8 โดยไม่มีการเปลี่ยนแปลง
- สากล: สามารถแสดงอักขระ Unicode ใดๆ ก็ได้ รวมถึงสัญลักษณ์ทางเทคนิคและอิโมจิ
- ประสิทธิภาพในข้อความภาษาละติน: เมื่อใช้ 1 ไบต์สำหรับ ASCII ประหยัดพื้นที่เมื่อเทียบกับ UTF-16 ในภาษาตะวันตกมากมาย
- การซิงโครไนซ์และการตรวจจับด้วยตนเอง: รูปแบบบิตอนุญาต ตรวจจับจุดเริ่มต้นของตัวละคร และตรวจสอบลำดับได้อย่างง่ายดาย
ข้อจำกัดและข้อแลกเปลี่ยน :
- ข้อความ CJK ใช้พื้นที่มากกว่าข้อความ UTF-16ซึ่งอักขระจำนวนมากเหล่านี้สามารถใส่ลงในไบต์คงที่ 2 ตัวได้
- ต้นทุนการคำนวณ: มีความยาวแปรผัน การดำเนินการบางอย่าง (เช่น "ไปที่อักขระ n") ต้องดำเนินการตั้งแต่ต้นและงานบางอย่างอาจเร็วกว่าในรูปแบบ UTF-16/UTF-32
BOM (Byte Order Mark) ใน UTF-8
UTF-8 ไม่จำเป็นต้องมี BOM เพราะลำดับไบต์ไม่เปลี่ยนความหมายของค่า (หน่วยที่เล็กที่สุดคือไบต์) ถึงอย่างนั้นก็ตาม มี BOM ให้เลือกอักขระ U+FEFF เข้ารหัสเป็น EF BB BF ที่จุดเริ่มต้นของไฟล์หรือสตรีม ซึ่งสามารถใช้เพื่อระบุว่า “นี่คือ Unicode/UTF-8”
แนวทางปฏิบัติที่ดีที่สุด : หากปรากฏที่จุดเริ่มต้น บางระบบจะยอมรับ ในขณะที่บางระบบจะตีความตามตัวอักษรในการต่อข้อความ ควรลบ BOM ระหว่างกลางออก การรวม BOM ไม่ใช่ข้อบังคับ และประโยชน์ของมันใน UTF-8 มีจำกัดเมื่อเทียบกับ UTF-16/UTF-32 ซึ่ง BOM จะระบุลำดับไบต์
ข้อผิดพลาดในการเขียนโค้ดทั่วไปและวิธีรับมือ
ตัวถอดรหัส UTF-8 ที่มีประสิทธิภาพจะต้องปฏิเสธลำดับที่ไม่ถูกต้องหรือแทนที่ด้วย U+FFFD (อักขระทดแทน) หรือแจ้งข้อผิดพลาด ข้อผิดพลาดที่พบบ่อยที่สุด ได้แก่:
- ลำดับที่ถูกตัดทอน: ไบต์นำหลายไบต์ที่ไม่มีความต่อเนื่องเพียงพอ
- ไบต์ต่อเนื่องหลวม: ปรากฏ
10xxxxxxโดยไม่มีไบต์นำที่ถูกต้อง - ความยาวเกิน: การเข้ารหัสด้วยไบต์มากกว่าที่จำเป็น เช่น การพยายามเข้ารหัส ASCII ด้วย 2 ไบต์ (
0xC0y0xC1ไม่ถูกต้อง). - ความยาวที่ห้าม: เริ่มแนะนำ 5 หรือ 6 ไบต์ (
0xF8-0xFDไม่ถูกต้อง ในมาตรฐาน UTF-8) - ค่าที่อยู่นอกช่วง Unicode: ไม่รองรับเหนือ U+10FFFF; ค่าบางอย่าง (
0xF5-0xF7เป็นจุดเริ่มต้น) ถือเป็นโมฆะ - คู่ตัวแทน UTF-16:
D800–DFFFไม่ใช่จุดรหัสที่ถูกต้อง ในรูปแบบ Unicode ไม่ควรปรากฏเป็นรหัส UTF-8
เมื่อคุณเห็นอักขระ “�” บนหน้าจอส่วนใหญ่แล้วมักเกิดจากการเข้ารหัสที่ไม่ตรงกัน หรือไฟล์ถูกบันทึกด้วยชุดรหัสที่แตกต่างกัน วิธีแก้ไขคือบังคับใช้การเข้ารหัส UTF-8 แบบครบวงจร (ไฟล์ เซิร์ฟเวอร์ ฐานข้อมูล และส่วนหัว HTTP)
UTF-8 บนเว็บและในอีเมล
หน้าเว็บ HTML ต้องการการกำหนดการเข้ารหัสเพียงอย่างเดียวเท่านั้นการเข้ารหัสที่แนะนำเพื่อความเข้ากันได้และขอบเขตการใช้งานคือ UTF-8 ควรเพิ่มแท็ก meta ต่อไปนี้ในส่วนหัวโดยเร็วที่สุด:
<meta charset="UTF-8">
วางไว้ที่จุดเริ่มต้นของแท็ก `<head>`เพื่อให้เบราว์เซอร์อ่านก่อนประมวลผลเอกสาร ซึ่งจะช่วยป้องกันความไม่สอดคล้องกันและอักขระที่ "ผิดเพี้ยน" การใช้งาน UTF-8 บนเว็บนั้นแพร่หลายอย่างมาก เว็บไซต์ส่วนใหญ่ในปัจจุบันใช้รูปแบบนี้
ในอีเมลนั้นUTF-8 ได้รับการสนับสนุนและแนะนำอย่างกว้างขวางจากองค์กรต่างๆ เช่น Internet Mail Consortium การตั้งค่าโปรแกรมอีเมลให้ใช้ UTF-8จะช่วยลดปัญหาเมื่อแลกเปลี่ยนข้อความกับผู้ที่ใช้ภาษาอื่น
UTF-8, UTF-16 และ UTF-32 มีความแตกต่างกันอย่างไร?
UTF-8 : การเข้ารหัสแบบความยาวแปรผันในหน่วย 8 บิตเหมาะสำหรับเว็บมีประสิทธิภาพสูงกับ ASCII และภาษาตะวันตก มีความเข้ากันได้ดีเยี่ยมและตรวจจับข้อผิดพลาดได้ดี
UTF-16 : ความยาวแปรผันในหน่วย 16 บิต ใช้คู่ตัวอักษรทดแทนสำหรับ U+10000 ขึ้นไปมักมีประโยชน์เมื่ออักขระที่ไม่ใช่ ASCII เป็นจำนวนมากและใช้ใน API และแพลตฟอร์มหลายแห่ง (ตัวอย่างเช่นWindows ทำงานในโหมด UTF-16 โดยตรง )
UTF-32 : ความยาวคงที่ 32 บิตต่ออักขระง่ายต่อการจัดทำดัชนีแต่ใช้พื้นที่มาก จึงสงวนไว้สำหรับกรณีที่ขนาดมีความสำคัญรองลงมาจากความเรียบง่ายในการประมวลผล
ตัวแปรที่เข้ากันไม่ได้: CESU-8 และ “Modified UTF-8”
CESU-8เข้ารหัสหน่วย UTF-16 โดยตรง (รวมถึงคู่ตัวอักษรทดแทน) แทนที่จะเข้ารหัสจุดรหัสดังนั้นจึงแตกต่างจาก UTF-8 มาตรฐานสำหรับอักขระที่สูงกว่า U+FFFF แพลตฟอร์มเก่าบางแพลตฟอร์มเคยใช้CESU-8 เช่น Oracle 8 ที่ใช้ชื่อเรียกแทน UTF-8และตั้งแต่ Oracle 9 เป็นต้นไป ก็ได้เพิ่ม UTF-8 มาตรฐานภายใต้ชื่อเรียกแทนอื่นJava และ Tcl ก็เคยใช้ CESU-8ในบางบริบทเช่นกัน
UTF-8 ที่ได้รับการดัดแปลง (เช่น ในสภาพแวดล้อม Java) จะแสดงอักขระ NUL (U+0000) เป็น 0xC0 0x80แทนที่จะเป็น 0x00 วิธีนี้ช่วยหลีกเลี่ยงไบต์ว่างในสตริง Cแต่ไม่เป็นไปตามมาตรฐาน UTF-8 การใช้งานเวอร์ชัน "ที่ได้รับการดัดแปลง" นี้จำนวนมากยังเป็นไปตามมาตรฐาน CESU-8ด้วย
UTF-8 บน Windows และ API: หน้าโค้ดและการแปลง
Windows ทำงานภายในในรูปแบบ UTF-16 (WCHAR)แต่ตั้งแต่ Windows 10 เวอร์ชัน 1903 คุณสามารถทำได้ บังคับให้ UTF-8 เป็นหน้าโค้ดกระบวนการ ผ่านทางแอปพลิเคชัน manifest (คุณสมบัติ activeCodePage) ซึ่งจะทำให้โค้ดเก่าที่ใช้ API “-A” ทำงานบน UTF-8 ได้ง่ายขึ้น
API -A เทียบกับ -W: -A ขึ้นอยู่กับหน้ารหัส ANSI กำหนดค่า (สามารถเป็น CP_UTF8) ในขณะที่ -W พวกเขาใช้ UTF-16. เพื่อทำงานร่วมกัน มัลติไบต์เป็นไวด์ชาร์ y ไวด์ชาร์ทูมัลติไบต์ ช่วยให้คุณสามารถแปลงระหว่าง UTF-8 และ UTF-16 ได้ สหรัฐอเมริกา CP_UTF8 และถ้ามีการใช้ MB_ERR_INVALID_CHARS เพื่อตรวจจับข้อผิดพลาดในการป้อนข้อมูล
UTF-8 สามารถใช้งานร่วมกับเบราว์เซอร์สมัยใหม่ (Chrome, Firefox, Safari, Edge, Opera และ Internet Explorer เวอร์ชันล่าสุด) และระบบปฏิบัติการส่วนใหญ่ (Windows, Linux, macOS, Android, iOS) เว้นแต่ว่าคุณจะใช้ซอฟต์แวร์ที่เก่ามากคุณก็ไม่น่าจะมีปัญหาอะไร
วิธีการแปลงไฟล์เป็น UTF-8
ใน Windows (Notepad) : เปิดไฟล์ ไปที่ "ไฟล์ > บันทึกเป็น..." แล้วในช่อง "การเข้ารหัส" ให้เลือกUTF-8บันทึกด้วยชื่อใหม่หากต้องการเก็บไฟล์เดิมไว้
ใน macOS (TextEdit) : ใน “TextEdit > การตั้งค่า > เปิดและบันทึก” ให้เลือกUnicode (UTF-8)เมื่อบันทึก จากนั้นส่งออกไฟล์โดยเปิดใช้งานตัวเลือกนั้นไว้
บน Linux: ด้วยเทอร์มินัลคุณสามารถใช้ iconv. ตัวอย่างเช่น iconv -f <codificación_origen> -t UTF-8 <entrada> -o <salida>. ตรวจสอบภายหลัง ซึ่งแอพพลิเคชันที่ใช้ก็คาดหวัง UTF-8 เช่นกัน
จะตรวจสอบได้อย่างไรว่าไฟล์นั้นใช้การเข้ารหัส UTF-8?โปรแกรมแก้ไขข้อความสมัยใหม่หลายโปรแกรมจะแสดงข้อมูลนี้ในแถบสถานะ หากคุณเห็นอักขระแปลก ๆ เช่น “�”, เครื่องหมายเน้นเสียงผิดเพี้ยน หรือ “ñ/ç” ที่แสดงผลไม่ถูกต้อง ให้ตรวจสอบการเข้ารหัสไฟล์และการตั้งค่าของโปรแกรมแก้ไข/เซิร์ฟเวอร์/ฐานข้อมูล
แนวทางปฏิบัติที่ดีเพื่อหลีกเลี่ยงความประหลาดใจ
กำหนดการเข้ารหัส UTF-8 ให้เร็วที่สุดเท่าที่จะเป็นไปได้ใน HTML และส่วนหัว HTTP จัดรูปแบบการเข้ารหัสให้สอดคล้องกันตลอดทั้งระบบ (ไฟล์ต้นฉบับ เทมเพลต ฐานข้อมูล และการเชื่อมต่อ) หลีกเลี่ยงการผสมการเข้ารหัสในหน้าเดียวกันหรือในขั้นตอนเดียวกัน และใช้เครื่องมือที่ตรวจสอบ/ปรับมาตรฐานข้อมูลขาเข้า
สำหรับการบูรณาการและ API, ระบุการเข้ารหัสในส่วนหัวเสมอ (Content-Type: application/json; charset=UTF-8ตัวอย่างเช่น) ทดสอบด้วยข้อมูลหลายภาษา (สำเนียง CJK อิโมจิ) เพื่อค้นหาจุดอ่อนก่อนการผลิต
UTF-8 ได้รับความนิยมเพราะมีความสมดุลระหว่างความเข้ากันได้ ประสิทธิภาพ และการครอบคลุมเป็นวิธีที่เหมาะสมที่สุดในการรับประกันว่าข้อความจะส่งต่อได้อย่างสมบูรณ์ข้ามวัฒนธรรม ระบบ และแอปพลิเคชันต่างๆ โดยไม่คำนึงถึงว่าข้อความนั้นจะมีเครื่องหมายเน้นเสียง สัญลักษณ์ทางเทคนิค หรืออักษรที่ไม่ใช่ภาษาละตินหรือไม่