UTF-8“ การเข้ารหัสความกว้างตัวแปร” ทำงานอย่างไร


110

มาตรฐาน Unicode มีจุดรหัสเพียงพอที่คุณต้องใช้ 4 ไบต์ในการจัดเก็บทั้งหมด นั่นคือสิ่งที่การเข้ารหัส UTF-32 ทำ แต่การเข้ารหัส UTF-8 ก็บีบให้สิ่งเหล่านี้มีช่องว่างเล็กลงมากโดยใช้สิ่งที่เรียกว่า "การเข้ารหัสความกว้างตัวแปร"

ในความเป็นจริงมันสามารถแทนอักขระ 127 ตัวแรกของ US-ASCII ได้เพียงหนึ่งไบต์ซึ่งดูเหมือน ASCII จริงดังนั้นคุณสามารถตีความข้อความ ascii จำนวนมากราวกับว่าเป็น UTF-8 โดยไม่ต้องทำอะไรเลย เคล็ดลับเรียบร้อย แล้วมันทำงานอย่างไร?

ฉันจะถามและตอบคำถามของตัวเองที่นี่เพราะฉันเพิ่งอ่านไปพอสมควรและฉันคิดว่ามันอาจช่วยคนอื่นได้บ้าง นอกจากนี้อาจมีใครแก้ไขฉันได้ถ้าฉันทำผิด


8
Straight Unicode ไม่ต้องการ 32 บิตในการเข้ารหัสจุดรหัสทั้งหมด ครั้งหนึ่งพวกเขาอ้างสิทธิ์ในจุดรหัสที่เป็นไปได้มากมาย แต่หลังจาก UTF-8 ถอดออกพวกเขาตั้งใจ จำกัด ตัวเองไว้ที่ 21 บิตดังนั้น UTF-8 จะไม่เกิน 4 ไบต์ต่ออักขระ ปัจจุบัน Unicode ต้องการเพียง 17 บิตเพื่อเก็บจุดรหัสที่เป็นไปได้ทั้งหมด หากไม่มีข้อ จำกัด นี้ UTF-8 อาจไปได้ถึง 6 ไบต์ต่ออักขระ
Warren Young

@ Warren: ส่วนใหญ่ถูกต้อง แต่ Unicode เป็นรหัส 21 บิต (U + 0000 ถึง U + 10FFFF)
Jonathan Leffler

2
@ Warren: UTF-8 จำกัด 4 ไบต์สามารถรองรับได้ถึง U + 1FFFFF ข้อ จำกัด ของ U + 10FFFF ถูกสร้างขึ้นเพื่อประโยชน์ของ UTF-16
dan04

@ dan04 เรามีคำอธิบายง่ายๆไหมว่ามันถูก จำกัด ไว้ที่ U + 10FFFF โดย UTF-16 หรือไม่? จะเป็นการดีที่จะทราบข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้
A-letubby

@ A-letubby: เนื่องจากรหัส UTF-16“ ตัวแทน” ได้รับการจัดสรรทำให้มีตัวแทนลูกค้าเป้าหมาย 1024 คนและตัวแทนเส้นทาง 1024 คน (และสามารถใช้เป็นคู่ได้เท่านั้น) เพื่อสร้างอักขระเพิ่มเติม 2 ^ 20 (ประมาณล้านตัว) พร้อมใช้งานนอกเหนือจาก BMP เพิ่มไปยังอักขระ 2 ^ 16 ที่มีอยู่ใน BMP ซึ่งทำให้เป็นไปได้ 0x110000 อักขระ
dan04

คำตอบ:


129

แต่ละไบต์เริ่มต้นด้วยบิตสองสามบิตที่บอกคุณว่าเป็นจุดรหัสไบต์เดียวจุดรหัสหลายไบต์หรือความต่อเนื่องของจุดรหัสหลายไบต์ แบบนี้:

0xxx xxxx    A single-byte US-ASCII code (from the first 127 characters)

โค้ดแบบหลายไบต์แต่ละจุดเริ่มต้นด้วยบิตสองสามบิตซึ่งโดยพื้นฐานแล้วพูดว่า "เฮ้คุณต้องอ่านไบต์ถัดไป (หรือสองหรือสาม) เพื่อดูว่าฉันเป็นอะไร" พวกเขาเป็น:

110x xxxx    One more byte follows
1110 xxxx    Two more bytes follow
1111 0xxx    Three more bytes follow

สุดท้ายไบต์ที่ตามหลังรหัสเริ่มต้นเหล่านั้นมีลักษณะดังนี้:

10xx xxxx    A continuation of one of the multi-byte characters

เนื่องจากคุณสามารถบอกได้ว่าคุณกำลังดูไบต์ประเภทใดจากสองสามบิตแรกแม้ว่าจะมีบางสิ่งบางอย่างพังทลายไปที่ไหนก็ตามคุณจะไม่สูญเสียลำดับทั้งหมด


14
มีเรื่องราวมากกว่านั้น - เนื่องจากการเข้ารหัสต้องเป็นการเข้ารหัสที่สั้นที่สุดเท่าที่จะเป็นไปได้สำหรับอักขระซึ่งท้ายที่สุดหมายความว่าไบต์ 0xC0 และ 0xC1 ไม่สามารถปรากฏใน UTF-8 ได้เช่น และในความเป็นจริง 0xF5..0xFF ไม่ได้ ดูคำถามที่พบบ่อยเกี่ยวกับ UTF-8 ที่unicode.org/faq/utf_bom.htmlหรือunicode.org/versions/Unicode5.2.0/ch03.pdf
Jonathan Leffler

2
เหตุใดจึงใช้อักขระเพียงตัวเดียวในการพูดnext char is continuationไม่ได้ ถ้าเรามีอักขระ 3 ไบต์มันก็จะเป็นเช่น1xxxxxxx 1xxxxxxx 0xxxxxxxนั้นก็จะเสียพื้นที่น้อยลง

9
@Soaku ทำให้ UTF-8 เป็นรหัสที่เรียกว่า "self-synchronizing" ซึ่งหมายความว่าหากมีข้อผิดพลาดบางส่วนของลำดับหายไปก็เป็นไปได้ที่จะตรวจพบและทิ้งสิ่งที่อ่านไม่ออก หากคุณอ่านไบต์ที่ขึ้นต้นด้วย 10xx และไม่มีไบต์ "เริ่มต้น" นำหน้าคุณสามารถละทิ้งมันได้เนื่องจากไม่มีความหมาย หากคุณมีระบบดังที่คุณอธิบายไว้และหนึ่งในไบต์แรกหายไปคุณอาจลงเอยด้วยอักขระอื่นที่ถูกต้องโดยไม่มีข้อบ่งชี้ข้อผิดพลาดใด ๆ นอกจากนี้ยังช่วยให้ง่ายต่อการค้นหาอักขระที่ถูกต้องถัดไปรวมทั้งแก้ไขสำหรับไบต์ "ความต่อเนื่อง" ที่ขาดหายไป
htmlcoderexe

9

RFC3629 - UTF-8 ซึ่งเป็นรูปแบบการเปลี่ยนแปลงของ ISO 10646เป็นหน่วยงานสุดท้ายที่นี่และมีคำอธิบายทั้งหมด

กล่าวโดยย่อคือใช้หลายบิตในแต่ละไบต์ของลำดับ 1-to-4-byte ที่เข้ารหัส UTF-8 ซึ่งเป็นตัวแทนของอักขระเดี่ยวเพื่อระบุว่าเป็นไบต์ต่อท้ายไบต์นำหน้าและหากเป็นเช่นนั้นจะมีกี่ไบต์ตามมา บิตที่เหลือมีน้ำหนักบรรทุก


1
อืมมมฉันโง่ฉันคิดว่า Unicode Standard เป็นหน่วยงานสุดท้ายของ UTF-8
John Machin

6
มาตรฐาน Unicode กำหนด Unicode เอง ไม่ได้กำหนดวิธีการต่างๆทั้งในปัจจุบันและอนาคตที่สามารถใช้ในการเข้ารหัสข้อความ Unicode เพื่อวัตถุประสงค์ต่างๆ (เช่นการจัดเก็บและการขนส่ง) UTF-8 เป็นหนึ่งในวิธีการเหล่านั้นและการอ้างอิงข้างต้นคือเอกสารที่กำหนด
azheglov

1
RFC3629 หน้า 3 ส่วนที่ 3 ระบุว่า "UTF-8 ถูกกำหนดโดย Unicode Standard"
John Machin

การไล่ลิงก์บน unicode.org ทำให้ฉันไปที่หัวข้อ 3.9 ของ Unicode Standardและคำจำกัดความเฉพาะ D92 (และ D86 เชิงสัมผัสด้วย) ฉันไม่รู้ว่าลิงก์นี้จะมีประโยชน์เพียงใดเมื่อมีการเผยแพร่เวอร์ชันใหม่ แต่ฉันคิดว่าพวกเขาต้องการให้ส่วนและตัวระบุคำจำกัดความมีเสถียรภาพในทุกเวอร์ชัน
tripleee

4

UTF-8 เป็นอีกระบบหนึ่งสำหรับจัดเก็บสตริงของจุดรหัส Unicode ของคุณซึ่งเป็นตัวเลข U + เวทย์มนตร์เหล่านั้นในหน่วยความจำโดยใช้ 8 บิตไบต์ ใน UTF-8 ทุกจุดรหัสตั้งแต่ 0-127 จะถูกเก็บไว้ในไบต์เดียว เฉพาะจุดรหัส 128 ขึ้นไปเท่านั้นที่จะจัดเก็บโดยใช้ 2, 3 ในความเป็นจริงสูงสุด 6 ไบต์

ตัดตอนมาจากขั้นต่ำที่แน่นอนนักพัฒนาซอฟต์แวร์ทุกคนอย่างแน่นอนต้องรู้เกี่ยวกับ Unicode และชุดอักขระในเชิงบวก (ไม่มีข้อแก้ตัว!)


นั่นเป็นบทความที่ดี แต่ดูเหมือนว่า Joel จะผิดเกี่ยวกับความยาวสูงสุดของลำดับ หน้า Wikipedia แสดง 1..4 ไบต์ต่ออักขระเท่านั้น
ผ่อนคลาย

4
ดังที่ฉันได้กล่าวไว้ข้างต้นเมื่อ UTF-8 ถูกสร้างขึ้นครั้งแรก Unicode อ้างว่ามีจุดรหัสมากถึง 32 บิตไม่ใช่เพราะพวกเขาต้องการจริงๆเพียงเพราะ 32 บิตเป็นค่าที่สะดวกและพวกเขาก็พัดผ่านมาแล้ว ขีด จำกัด ก่อนหน้าของอักขระ 16 บิต หลังจาก UTF-8 ได้รับการพิสูจน์แล้วว่าเป็นที่นิยมพวกเขาเลือกที่จะ จำกัด จำนวนจุดรหัสสูงสุดตลอดกาลไว้ที่ 2 ^ 21 ซึ่งเป็นค่าที่ใหญ่ที่สุดที่คุณสามารถเข้ารหัสด้วยโครงร่าง UTF-8 ขนาด 4 ไบต์ ยังมีอักขระน้อยกว่า 2 ^ 17 ใน Unicode ดังนั้นเราจึงสามารถเพิ่มจำนวนอักขระใน Unicode ได้มากกว่าสี่เท่าด้วยรูปแบบใหม่นี้
Warren Young

ตกลง แต่ไม่ใช่คำอธิบายที่ถามโดย OP
Nishant

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