ความแตกต่างระหว่าง UTF-8, UTF-16 และ UTF-32 คืออะไร
ฉันเข้าใจว่าพวกเขาจะเก็บ Unicode ทั้งหมดและแต่ละตัวใช้จำนวนไบต์ที่แตกต่างกันเพื่อแสดงอักขระ มีข้อได้เปรียบในการเลือกอย่างใดอย่างหนึ่งหรือไม่?
ความแตกต่างระหว่าง UTF-8, UTF-16 และ UTF-32 คืออะไร
ฉันเข้าใจว่าพวกเขาจะเก็บ Unicode ทั้งหมดและแต่ละตัวใช้จำนวนไบต์ที่แตกต่างกันเพื่อแสดงอักขระ มีข้อได้เปรียบในการเลือกอย่างใดอย่างหนึ่งหรือไม่?
คำตอบ:
UTF-8 มีข้อได้เปรียบในกรณีที่อักขระ ASCII แสดงถึงตัวอักษรส่วนใหญ่ในบล็อกข้อความเนื่องจาก UTF-8 เข้ารหัสสิ่งเหล่านี้เป็น 8 บิต (เช่น ASCII) นอกจากนี้ยังมีประโยชน์ในกรณีที่ไฟล์ UTF-8 ที่มีอักขระ ASCII เท่านั้นที่มีการเข้ารหัสเช่นเดียวกับไฟล์ ASCII
UTF-16 นั้นดีกว่าโดยที่ ASCII นั้นไม่ได้เด่นกว่าเนื่องจากมันใช้ 2 ไบต์ต่อตัวอักษรเป็นหลัก UTF-8 จะเริ่มใช้ 3 ไบต์ขึ้นไปสำหรับอักขระลำดับที่สูงขึ้นโดยที่ UTF-16 ยังคงอยู่ที่ 2 ไบต์สำหรับอักขระส่วนใหญ่
UTF-32 จะครอบคลุมอักขระที่เป็นไปได้ทั้งหมดใน 4 ไบต์ ทำให้มันป่องสวย ฉันไม่คิดว่าจะได้ประโยชน์จากการใช้มัน
ในระยะสั้น:
wchar_t
จะมีค่าเริ่มต้นเป็น 4 ไบต์ gcc มีตัวเลือก-fshort-wchar
ที่ลดขนาดเป็น 2 ไบต์ แต่แบ่งความเข้ากันได้แบบไบนารีกับ std libs
UTF-8 เป็นตัวแปร1 ถึง 4ไบต์
UTF-16 เป็นตัวแปร2 หรือ 4ไบต์
UTF-32 ได้รับการแก้ไข4ไบต์
หมายเหตุ: UTF-8 สามารถใช้เวลา 1 ถึง 6 ไบต์ด้วยการประชุมล่าสุด: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
Unicode กำหนดชุดอักขระขนาดใหญ่เพียงชุดเดียวโดยกำหนดค่าจำนวนเต็มหนึ่งค่าให้กับสัญลักษณ์กราฟิกทุกอัน (นั่นคือการทำให้เข้าใจง่ายที่สำคัญและไม่เป็นความจริง แต่ใกล้พอสำหรับจุดประสงค์ของคำถามนี้) UTF-8/16/32 เป็นวิธีที่แตกต่างกันในการเข้ารหัสสิ่งนี้
โดยย่อ UTF-32 ใช้ค่า 32- บิตสำหรับแต่ละอักขระ ที่ช่วยให้พวกเขาใช้รหัสความกว้างคงที่สำหรับตัวละครทุกตัว
UTF-16 ใช้ 16 บิตโดยค่าเริ่มต้น แต่นั่นให้เพียง 65k อักขระที่เป็นไปได้ซึ่งใกล้พอสำหรับชุด Unicode เต็ม ดังนั้นตัวละครบางตัวใช้คู่ของค่า 16 บิต
และ UTF-8 ใช้ค่า 8 บิตตามค่าเริ่มต้นซึ่งหมายความว่า 127 ค่าแรกคืออักขระไบต์เดียวแบบความกว้างคงที่ (บิตที่สำคัญที่สุดใช้เพื่อแสดงว่านี่เป็นจุดเริ่มต้นของลำดับแบบหลายไบต์โดยเหลือ 7 บิตสำหรับค่าอักขระจริง) อักขระอื่นทั้งหมดถูกเข้ารหัสตามลำดับสูงสุด 4 ไบต์ (หากหน่วยความจำทำหน้าที่)
และนั่นทำให้เราได้เปรียบ อักขระ ASCII ใด ๆ เข้ากันได้กับ UTF-8 โดยตรงดังนั้นสำหรับการอัปเกรดแอปรุ่นเก่า UTF-8 เป็นตัวเลือกทั่วไปและชัดเจน ในเกือบทุกกรณีมันจะใช้หน่วยความจำน้อยที่สุด ในทางกลับกันคุณไม่สามารถรับรองความกว้างของตัวละครได้ อาจมีความกว้างอักขระ 1, 2, 3 หรือ 4 ตัวซึ่งทำให้การจัดการสตริงทำได้ยาก
UTF-32 นั้นตรงกันข้ามใช้หน่วยความจำมากที่สุด (อักขระแต่ละตัวกว้าง 4 ไบต์คงที่) แต่ในทางกลับกันคุณรู้ว่าตัวละครทุกตัวมีความยาวที่แม่นยำนี้ดังนั้นการจัดการสตริงจึงง่ายกว่ามาก คุณสามารถคำนวณจำนวนตัวอักษรในสตริงได้จากความยาวเป็นไบต์ของสตริง คุณไม่สามารถทำได้ด้วย UTF-8
UTF-16 คือการประนีประนอม มันช่วยให้ตัวละครส่วนใหญ่พอดีกับค่า 16 บิตความกว้างคงที่ ดังนั้นตราบใดที่คุณไม่มีสัญลักษณ์ภาษาจีนโน้ตดนตรีหรืออื่น ๆ คุณสามารถสรุปได้ว่าอักขระแต่ละตัวมีความกว้าง 16 บิต มันใช้หน่วยความจำน้อยกว่า UTF-32 แต่มันก็มีบางวิธี "ที่เลวร้ายที่สุดของโลกทั้งสอง" มันใช้หน่วยความจำมากกว่า UTF-8 เกือบทุกครั้งและมันก็ไม่ได้หลีกเลี่ยงปัญหาที่เกิดขึ้นกับ UTF-8
ในที่สุดมันก็มักจะมีประโยชน์ที่จะไปกับสิ่งที่แพลตฟอร์มรองรับ Windows ใช้ UTF-16 ภายในดังนั้นสำหรับ Windows นั่นเป็นตัวเลือกที่ชัดเจน
Linux แตกต่างกันเล็กน้อย แต่โดยทั่วไปจะใช้ UTF-8 สำหรับทุกสิ่งที่สอดคล้องกับ Unicode
คำตอบสั้น ๆ : การเข้ารหัสทั้งสามสามารถเข้ารหัสชุดอักขระเดียวกันได้ แต่จะแทนอักขระแต่ละตัวเป็นลำดับไบต์ที่แตกต่างกัน
Unicodeเป็นมาตรฐานและเกี่ยวกับUTF-xคุณสามารถคิดว่าเป็นการใช้งานด้านเทคนิคเพื่อการใช้งานจริง:
ฉันพยายามที่จะให้คำอธิบายง่ายๆในของฉันblogpost
ต้องใช้ 32 บิต (4 ไบต์) เพื่อเข้ารหัสอักขระใด ๆ ตัวอย่างเช่นในการเป็นตัวแทนของรหัสอักขระ A โดยใช้ชุดรูปแบบนี้คุณจะต้องเขียน 65 ในเลขฐานสองแบบ 32 บิต:
00000000 00000000 00000000 01000001 (Big Endian)
หากคุณมองให้ใกล้ชิดคุณจะทราบว่าเจ็ดบิตที่ถูกต้องที่สุดนั้นเป็นบิตเดียวกันเมื่อใช้รูปแบบ ASCII แต่เนื่องจาก UTF-32 เป็นแบบแผนความกว้างคงที่เราต้องแนบสามไบต์เพิ่มเติม หมายความว่าหากเรามีไฟล์สองไฟล์ที่มีอักขระ "A" เท่านั้นไฟล์หนึ่งจะถูกเข้ารหัส ASCII และอีกไฟล์หนึ่งเข้ารหัส UTF-32 ขนาดของไฟล์จะเป็น 1 ไบต์และ 4 ไบต์ตามลำดับ
หลายคนคิดว่าเนื่องจาก UTF-32 ใช้ความกว้างคงที่ 32 บิตเพื่อเป็นตัวแทนของรหัสจุด UTF-16 จึงเป็นความกว้างคงที่ 16 บิต ไม่ถูกต้อง!
ใน UTF-16 รหัสจุดอาจแทนทั้ง 16 บิตหรือ 32 บิต ดังนั้นโครงร่างนี้คือระบบเข้ารหัสความยาวผันแปร ข้อดีของ UTF-32 คืออะไร? อย่างน้อยสำหรับ ASCII ขนาดของไฟล์จะไม่เป็น 4 เท่าของต้นฉบับ (แต่ยังคงเป็นสองเท่า) ดังนั้นเราจึงยังไม่รองรับ ASCII แบบย้อนหลัง
เนื่องจาก 7-bits เพียงพอที่จะเป็นตัวแทนของอักขระ "A" ตอนนี้เราสามารถใช้ 2 ไบต์แทน 4 เช่น UTF-32 มันจะมีลักษณะ:
00000000 01000001
คุณเดาถูก .. ใน UTF-8 จุดรหัสอาจแทนด้วย 32, 16, 24 หรือ 8 บิตและเป็นระบบ UTF-16 อันนี้ก็เป็นระบบเข้ารหัสความยาวตัวแปร
ในที่สุดเราสามารถเป็นตัวแทน "A" ในลักษณะเดียวกับที่เราเป็นตัวแทนโดยใช้ระบบเข้ารหัส ASCII
01001101
พิจารณาตัวอักษรจีน "語" - การเข้ารหัส UTF-8 คือ:
11101000 10101010 10011110
ในขณะที่การเข้ารหัส UTF-16 นั้นสั้นลง:
10001010 10011110
เพื่อให้เข้าใจถึงการเป็นตัวแทนและวิธีตีความมันไปที่โพสต์ต้นฉบับ
UTF-8 จะเป็นพื้นที่ที่มีประสิทธิภาพที่สุดยกเว้นว่าตัวละครส่วนใหญ่นั้นมาจากพื้นที่ของตัวละคร CJK (จีนญี่ปุ่นและเกาหลี)
UTF-32 ที่ดีที่สุดสำหรับการเข้าถึงแบบสุ่มโดยตัวอักษรชดเชยเป็นไบต์อาร์เรย์
0xxxxxxx
เลขฐานสอง ทุกตัวอักษรสองไบต์เริ่มต้นด้วยกับไบต์ที่สองของ110xxxxx
10xxxxxx
ดังนั้นสมมติว่าอักขระตัวแรกของอักขระสองไบต์หายไป ทันทีที่คุณเห็น10xxxxxx
โดยไม่ต้องนำหน้า110xxxxxx
คุณสามารถกำหนดได้ว่าไบต์นั้นสูญหายหรือเสียหายและทิ้งอักขระนั้น (หรือขออีกครั้งจากเซิร์ฟเวอร์หรืออะไรก็ตาม) แล้วไปต่อจนกว่าคุณจะเห็นไบต์แรกที่ถูกต้องอีกครั้ง .
ฉันทำการทดสอบเพื่อเปรียบเทียบประสิทธิภาพของฐานข้อมูลระหว่าง UTF-8 และ UTF-16 ใน MySQL
ใน UTF-32 อักขระทั้งหมดมีรหัส 32 บิต ข้อดีคือคุณสามารถคำนวณความยาวของสตริงได้อย่างง่ายดาย ข้อเสียคือสำหรับแต่ละอักขระ ASCII คุณเสียสามไบต์พิเศษ
ในอักขระ UTF-8 มีความยาวผันแปรอักขระ ASCII จะถูกเข้ารหัสในหนึ่งไบต์ (แปดบิต) อักขระพิเศษตะวันตกส่วนใหญ่จะถูกเข้ารหัสในสองไบต์หรือสามไบต์ (ตัวอย่างเช่น€คือสามไบต์) และอักขระที่แปลกใหม่อาจใช้เวลานานขึ้น ถึงสี่ไบต์ ข้อเสียที่ชัดเจนคือว่านิรนัยที่คุณไม่สามารถคำนวณความยาวของสตริง แต่จะใช้เวลาน้อยกว่ามากในการเขียนข้อความอักษรละติน (อังกฤษ) เมื่อเทียบกับ UTF-32
UTF-16 ก็มีความยาวผันแปรเช่นกัน อักขระถูกเข้ารหัสทั้งสองไบต์หรือสี่ไบต์ ฉันไม่เห็นประเด็น มันมีข้อเสียของความยาวผันแปร แต่ไม่ได้ประโยชน์จากการประหยัดพื้นที่มากเท่ากับ UTF-8
จากทั้งสามอย่างชัดเจน UTF-8 เป็นที่แพร่หลายที่สุด
ขึ้นอยู่กับสภาพแวดล้อมการพัฒนาของคุณคุณอาจไม่มีทางเลือกว่าการเข้ารหัสชนิดข้อมูลสตริงของคุณจะใช้ภายในอะไร
แต่สำหรับการจัดเก็บและแลกเปลี่ยนข้อมูลฉันมักจะใช้ UTF-8 ถ้าคุณมีทางเลือก หากคุณมีข้อมูล ASCII เป็นส่วนใหญ่สิ่งนี้จะทำให้คุณถ่ายโอนข้อมูลได้น้อยที่สุดในขณะที่ยังสามารถเข้ารหัสได้ทุกอย่าง การปรับให้เหมาะสมสำหรับ I / O อย่างน้อยที่สุดคือวิธีการใช้เครื่องจักรที่ทันสมัย
ความแตกต่างคือขนาดของตัวแปรพื้นฐานซึ่งในแต่ละกรณีจะมีขนาดใหญ่ขึ้นเพื่อให้สามารถแสดงอักขระได้มากขึ้น
อย่างไรก็ตามแบบอักษรการเข้ารหัสและสิ่งต่าง ๆ มีความซับซ้อนอย่างชั่วร้าย (โดยไม่จำเป็น?) ดังนั้นจำเป็นต้องมีลิงก์ขนาดใหญ่เพื่อกรอกรายละเอียดเพิ่มเติม:
http://www.cs.tut.fi/~jkorpela/chars.html#ascii
อย่าคาดหวังว่าจะเข้าใจมันทั้งหมด แต่ถ้าคุณไม่ต้องการมีปัญหาในภายหลังก็คุ้มค่าที่จะเรียนรู้ให้เร็วที่สุดเท่าที่จะทำได้
พอล
กล่าวโดยย่อเหตุผลเดียวที่ใช้ UTF-16 หรือ UTF-32 คือการสนับสนุนสคริปต์ที่ไม่ใช่ภาษาอังกฤษและภาษาโบราณตามลำดับ
ฉันสงสัยว่าทำไมทุกคนเลือกที่จะมีการเข้ารหัสที่ไม่ใช่ UTF-8 เมื่อเห็นได้ชัดว่ามันมีประสิทธิภาพมากกว่าสำหรับการใช้งานเว็บ / การเขียนโปรแกรม
ความเข้าใจผิดที่พบบ่อย - หมายเลขต่อท้ายไม่ได้บ่งบอกถึงความสามารถของมัน พวกเขาทั้งหมดสนับสนุน Unicode ที่สมบูรณ์เพียงแค่ที่ UTF-8 สามารถจัดการ ASCII ด้วยไบต์เดียวจึงมีประสิทธิภาพมากขึ้น / น้อยกว่าความเสียหายต่อ CPU และผ่านทางอินเทอร์เน็ต
อ่านบ้างดี: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html และhttp://utf8everywhere.org