- UTF-8 เป็นรูปแบบการเข้ารหัสแบบ ความยาวแปรผัน ที่สามารถแทนตัวอักษรได้หลายล้านตัว พร้อมทั้งยังคง ความเข้ากันได้ย้อนหลังกับ ASCII
- ช่วง 7 บิตเดียวกับ ASCII (
U+0000~U+007F) ใช้เป็น 1 ไบต์ ตามเดิม ทำให้ไฟล์ ASCII เป็นไฟล์ UTF-8 ที่ถูกต้องได้ในทันที
- ตัวอักษรอื่น ๆ จะแทนด้วยลำดับ 2~4 ไบต์ โดย รูปแบบบิต ของไบต์นำหน้าจะกำหนดความยาว และไบต์ถัดไปจะขึ้นต้นด้วย
10 เพื่อบ่งชี้ว่าเป็น continuation byte
- ด้วยการออกแบบนี้ UTF-8 จึงรองรับชุดอักขระสากลได้ ขณะเดียวกันก็ เข้ากันได้อย่างสมบูรณ์ กับระบบ ASCII เดิม จนกลายเป็นการเข้ารหัสอักขระที่ใช้แพร่หลายที่สุด
- การเข้ารหัสยูนิโค้ดแบบอื่นอย่าง UTF-16 และ UTF-32 ไม่ได้ให้ความเข้ากันได้กับ ASCII ในลักษณะนี้
ความยอดเยี่ยมของการออกแบบ UTF-8
- เมื่อได้รู้จักการเข้ารหัส UTF-8 ครั้งแรก ผู้เขียนประทับใจมากกับโครงสร้างที่สามารถครอบคลุมอักขระ นับล้านแบบ จากภาษาและสัญลักษณ์ที่แตกต่างกันภายใต้ระบบเดียว ขณะเดียวกันก็ยัง เข้ากันได้กับ ASCII เดิม
- โดยพื้นฐานแล้ว UTF-8 ใช้งานได้สูงสุด 32 บิต แต่ ASCII ใช้เพียง 7 บิต
- หลักการออกแบบของ UTF-8 มีดังนี้
- ไฟล์ที่เข้ารหัสแบบ ASCII ทุกไฟล์เป็น ไฟล์ UTF-8 ที่ถูกต้อง
- ไฟล์ UTF-8 ที่มีเฉพาะอักขระ ASCII ทั้งหมดก็เป็น ไฟล์ ASCII ที่ถูกต้อง
- แนวคิดในการ ผสาน ระบบเก่าที่จำกัดอยู่เพียง 128 ตัวอักษรเข้ากับระบบที่ครอบคลุมตัวอักษรนับล้านนั้นล้ำหน้ามาก
แนวคิดพื้นฐานของ UTF-8
- UTF-8 คือ การเข้ารหัสอักขระแบบความยาวแปรผัน (variable-width encoding) ที่ออกแบบมาเพื่อแทนตัวอักษรทั้งหมดใน ชุดอักขระยูนิโค้ด
- เข้ารหัสอักขระแต่ละตัวด้วย 1~4 ไบต์
- อักขระ 128 ตัวแรก (
U+0000~U+007F) จะถูกเก็บเป็น ไบต์เดียว เพื่อให้เข้ากันได้ย้อนหลังกับ ASCII
- อักขระอื่น ๆ จะถูกเข้ารหัสเป็น 2, 3 หรือ 4 ไบต์
- บิตนำหน้า ของไบต์ตัวแรกจะเป็นตัวกำหนดจำนวนไบต์ทั้งหมดที่ต้องใช้ในการเข้ารหัส
| รูปแบบ 1 ไบต์ |
จำนวนไบต์ |
รูปแบบลำดับไบต์ทั้งหมด |
| 0xxxxxxx |
1 |
0xxxxxxx (ASCII ทั่วไป) |
| 110xxxxx |
2 |
110xxxxx 10xxxxxx |
| 1110xxxx |
3 |
1110xxxx 10xxxxxx 10xxxxxx |
| 11110xxx |
4 |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
- ไบต์ลำดับที่ 2, 3 และ 4 ของลำดับหลายไบต์จะขึ้นต้นด้วย
10 เสมอ ซึ่งช่วย ระบุอย่างชัดเจนว่าเป็น continuation byte
- เมื่อนำบิตส่วนที่เหลือของไบต์หลักและ continuation byte มารวมกัน จะได้ code point หนึ่งค่า
- code point คือรหัสระบุอักขระยูนิโค้ดแบบไม่ซ้ำ ซึ่งเขียนด้วยคำนำหน้า "U+" และเลขฐานสิบหก
- ตัวอย่าง: code point ของ "A" คือ
U+0041
- ขั้นตอนการตีความอักขระจากไบต์ของ UTF-8 มีดังนี้
- 1. อ่านไบต์หนึ่งตัว ถ้าขึ้นต้นด้วย 0 ให้ถือว่าเป็นอักขระไบต์เดียว (ASCII) ใช้ 7 บิตที่เหลือแทนอักขระนั้น แล้วไปยังไบต์ถัดไป
- 2. ถ้าไม่ใช่ 0
- ถ้าเป็น 110 ให้ถือว่าเป็นอักขระ 2 ไบต์ แล้วอ่านไบต์ถัดไปเพิ่มอีก 1 ไบต์
- ถ้าเป็น 1110 ให้ถือว่าเป็นอักขระ 3 ไบต์ แล้วอ่านไบต์ถัดไปเพิ่มอีก 2 ไบต์
- ถ้าเป็น 11110 ให้ถือว่าเป็นอักขระ 4 ไบต์ แล้วอ่านไบต์ถัดไปเพิ่มอีก 3 ไบต์
- 3. นำ บิตที่ไม่ใช่บิตนำหน้า จากไบต์ที่กำหนดแล้วมารวมกัน เพื่อใช้เป็นค่าไบนารีของ code point
- 4. หา code point นั้นในชุดอักขระยูนิโค้ด แล้วแสดงผลบนหน้าจอ
- 5. ทำซ้ำกับไบต์ถัดไป
ตัวอย่าง: อักขระภาษาฮินดี "अ"
- การแทนแบบ UTF-8:
11100000 10100100 10000101 (3 ไบต์)
- ไบต์แรก (
11100000) → แสดงว่าเป็นอักขระ 3 ไบต์
- การรวมบิตที่มีความหมายของทั้งสามไบต์ →
00001001 00000101 = เลขฐานสิบหก 0x0905
- code point
U+0905 หมายถึงอักษรเทวนาครี "अ"
ตัวอย่างไฟล์
-
1. Hey👋 Buddy
- มีทั้งหมด 13 ไบต์
- อักขระ ASCII (H, e, y, B, u, d, d, y, เว้นวรรค) → ตัวละ 1 ไบต์
- 👋 (U+1F44B) → 4 ไบต์
11110000 10011111 10010001 10001011
- ไฟล์นี้เป็น ไฟล์ UTF-8 ที่ถูกต้อง แต่เนื่องจากมีอักขระที่ไม่ใช่ ASCII (อีโมจิ) จึง ไม่ใช่ไฟล์ที่เข้ากันได้ย้อนหลังกับ ASCII
-
2. Hey Buddy
- มีทั้งหมด 9 ไบต์ และอยู่ในช่วง ASCII ทั้งหมด
- ดังนั้นไฟล์นี้จึงเป็นทั้ง ไฟล์ ASCII ที่ถูกต้อง และ ไฟล์ UTF-8 ที่ถูกต้อง
เปรียบเทียบกับการเข้ารหัสอื่น
- มีการเข้ารหัสบางแบบที่ให้ความเข้ากันได้กับ ASCII เช่นกัน แต่ ไม่ได้ถูกใช้อย่างแพร่หลายเท่า UTF-8
- GB18030 (มาตรฐานของจีน) เป็นต้น ก็ให้ความเข้ากันได้กับ ASCII แต่ไม่ได้ใช้อย่างแพร่หลาย
- ตระกูล ISO/IEC 8859 เป็นการขยายแบบไบต์เดียว (สูงสุด 256 ตัวอักษร) จึงมีข้อจำกัด
- UTF-16/UTF-32 ไม่มีความเข้ากันได้กับ ASCII
- 'A' (U+0041): UTF-16 คือ
00 41, UTF-32 คือ 00 00 00 41
โบนัส: UTF-8 Playground
ยังไม่มีความคิดเห็น