การเข้ารหัสและชุดอักขระแตกต่างกันอย่างไร


151

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

ฉันพบคำว่า "charset" ในส่วนหัวของอีเมลเช่นเดียวกับใน "ISO-2022-JP" แต่ไม่มีการเข้ารหัสในตัวแก้ไขข้อความ (ฉันมองไปรอบ ๆ เครื่องมือแก้ไขข้อความที่แตกต่างกัน)

การเข้ารหัสข้อความและชุดอักขระแตกต่างกันอย่างไร ฉันจะขอบคุณถ้าคุณสามารถแสดงตัวอย่างกรณีการใช้งานให้ฉันได้


ดูโพสต์นี้: stackoverflow.com/questions/13743250/…
rghome

คำตอบ:


144

โดยทั่วไป:

  1. charset เป็นชุดของอักขระที่คุณสามารถใช้ได้
  2. การเข้ารหัสเป็นวิธีที่อักขระเหล่านี้ถูกเก็บไว้ในหน่วยความจำ

42
จริง แต่ในการใช้งานจริง "charset" มักจะหมายถึงทั้งตัวละครและรูปแบบการเข้ารหัส
อลันมัวร์

@AlanMoore ในความเป็นจริงก็เช่นเดียวกันกับที่ผู้คนพูดว่า "เลขทศนิยม" เพื่ออ้างถึงตัวเลขใด ๆ ที่มี "ตัวคั่นทศนิยม" มันไม่ถูกต้องจริงๆ แต่ใช่คุณควรระวังว่าบางคนใช้มันอย่างนั้น
bvdb

2
นั่นไม่ถูกต้อง ตัวอย่างเช่น Unicode หมายถึงชุดอักขระ แต่มีการเข้ารหัสที่เป็นไปได้หลายรายการ (UTF-8, UTF-16, UTF-32)
rghome

84

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

อย่างไรก็ตามเราอยู่ระหว่างการเปลี่ยนไปใช้ Unicode ซึ่งรวมถึงชุดอักขระที่สามารถแสดงสคริปต์ทั่วโลกได้เกือบทั้งหมด อย่างไรก็ตามมีการเข้ารหัสหลายรหัสสำหรับ Unicode การเข้ารหัสเป็นวิธีการแมปสตริงของอักขระกับสตริงไบต์ ตัวอย่างของการเข้ารหัส Unicode ได้แก่UTF-8 , UTF-16 BEและUTF-16 LE แต่ละข้อได้เปรียบสำหรับการใช้งานเฉพาะหรือสถาปัตยกรรมเครื่อง


20
โปรดทราบว่า javadoc ใช้ "charset" แทนที่จะใช้ "encoding" อย่างผิด ๆ ตัวอย่างเช่นในInputStreamReaderเราอ่าน"An InputStreamReader เป็นบริดจ์จากไบต์สตรีมไปยังสตรีมอักขระ: มันอ่านไบต์และถอดรหัสเป็นอักขระโดยใช้ชุดอักขระที่ระบุ มันอาจใช้การระบุชื่อหรืออาจได้รับอย่างชัดเจนหรืออาจจะยอมรับชุดอักขระเริ่มต้นของแพลตฟอร์ม " . อย่างไรก็ตามสิ่งที่พวกเขาหมายถึงคือ "การเข้ารหัส"
David Tonhofer

4
ขอบคุณสำหรับคำอธิบายของคุณ Unicodeเป็นชุดตัวอักษรและUTF-8เป็นวิธีการเข้ารหัสหนึ่งUnicodeและUTF-16เป็นอีกวิธีการเข้ารหัสUnicode
HongchaoZhang

47

นอกเหนือจากคำตอบอื่น ๆ ฉันคิดว่าบทความนี้เป็นอ่านที่ดี http://www.joelonsoftware.com/articles/Unicode.html

บทความนี้มีบรรดาศักดิ์เป็น " แน่นอนทุกขั้นต่ำของผู้พัฒนาซอฟท์แวแน่นอนบวกต้องทราบเกี่ยวกับ Unicode และชุดตัวอักษร (ไม่มีข้อแก้ตัว!) " เขียนโดยโจ Spolsky เรียงความมีอายุมากกว่า 10 ปี แต่ (น่าเสียดาย) เนื้อหายังคงใช้ได้ ...


2
ขอบคุณมากสำหรับการแนะนำบทความ มันเป็นสิ่งที่ดี
TK

9
คำตอบนี้สามารถปรับปรุงได้โดยให้คำอธิบายสั้น ๆว่าทำไมฉันควรอ่านบทความของ Joel
james.garriss

@mattanja ลิงก์ที่คุณให้ไว้นั้นยอดเยี่ยมมาก ขอบคุณสำหรับการแบ่งปัน. โหวตขึ้น
hagrawal

1
ฉันต้องการนำบทความที่ยอดเยี่ยมนี้ซึ่งเป็นภาคผนวกของ Joel Spolsky เข้าด้วยกัน; kunststube.net/encoding
mkb

ฉันไม่เข้าใจบทความของ Joel เมื่ออ่านครั้งแรก แต่ฉันพบว่า powerpoint นี้มีความชัดเจนและเฉพาะเจาะจงมาก: unicode.org/notes/tn23/Muller-Slides+Narr.pdf
johnsimer

27

การเข้ารหัสอักขระประกอบด้วย:

  1. ชุดของอักขระที่รองรับ
  2. การแม็พระหว่างอักขระและจำนวนเต็ม ("จุดรหัส")
  3. วิธีการเข้ารหัสจุดรหัสเป็นชุดของ "รหัสหน่วย" (เช่นหน่วย 16 บิตสำหรับ UTF-16)
  4. วิธีการเข้ารหัสรหัสหน่วยเป็นไบต์ (เช่น big-endian หรือ little-endian)

ขั้นตอนที่ # 1 โดยตัวของมันเองคือ "ชุดอักขระตัวละคร" หรือชุดอักขระ "นามธรรม" และ # 1 + # 2 = เป็น "ชุดอักขระที่เข้ารหัส"

แต่ก่อนที่ Unicode จะได้รับความนิยมและทุกคน (ยกเว้นเอเชียตะวันออก) ใช้การเข้ารหัสไบต์เดียวขั้นตอนที่ 3 และ # 4 นั้นไม่สำคัญ (code point = code unit = byte) ดังนั้นโปรโตคอลที่เก่ากว่าจึงไม่แยกความแตกต่างอย่างชัดเจนระหว่าง "การเข้ารหัสอักขระ" และ "ชุดอักขระที่เข้ารหัส" โปรโตคอลเก่าใช้charsetเมื่อพวกเขาหมายถึงการเข้ารหัส


ทำไมเราถึงสามารถอ่าน charset = 'utf-8' ในแท็ก html META ได้ เพราะมันถูกนิยามมานานแล้ว
Eildosa

26

เพิ่มความสว่างให้กับผู้ที่มาเยี่ยมชมต่อจากนี้ไปหวังว่ามันจะมีประโยชน์


ชุดตัวอักษร

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

ตัวอย่างชุดอักขระ: ASCII (ครอบคลุมอักขระภาษาอังกฤษทั้งหมด), ISO / IEC 646, Unicode (ครอบคลุมอักขระจากภาษาที่มีชีวิตทั้งหมดในโลก)

ชุดอักขระรหัส

ชุดอักขระที่กำหนดรหัสคือชุดที่กำหนดหมายเลขเฉพาะให้กับอักขระแต่ละตัว หมายเลขที่ไม่ซ้ำนั้นเรียกว่า "จุดรหัส"
ชุดอักขระที่เขียนโค้ดบางครั้งเรียกว่าหน้ารหัส

การเข้ารหัส

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

ตัวอย่างการเข้ารหัส: ASCII, โครงร่างการเข้ารหัส Unicode เช่น UTF-8, UTF-16, UTF-32

อธิบายรายละเอียดของแนวคิด 3 ข้อข้างต้น

  • พิจารณาสิ่งนี้ - ตัวละคร 'क' ในชุดอักขระ Devanagari มีจุดรหัสทศนิยม2325 ซึ่งจะแสดงเป็นสองไบต์ ( 09 15) เมื่อใช้การเข้ารหัส UTF-16
  • ใน“ISO-8859-1” เข้ารหัสโครงการ“U” (นี่คืออะไร แต่ตัวละครในชุดตัวอักษรละติน) จะแสดงเป็นค่าเฮกซ่าทศนิยมของFCขณะที่อยู่ใน“UTF-8” มันแสดงเป็นC3 BCและ FE FF 00 FCUTF-16
  • แผนการเข้ารหัสที่แตกต่างกันอาจใช้จุดรหัสเดียวกันเพื่อแสดงอักขระที่แตกต่างกันตัวอย่างเช่นใน“ ISO-8859-1” (หรือเรียกอีกอย่างว่าละติน 1) ค่าจุดรหัสทศนิยมสำหรับตัวอักษร 'é' คือ 233 อย่างไรก็ตามใน ISO 8859-5 จุดรหัสเดียวกันแสดงถึงอักขระ Cyrillic 'щ'
  • ในอีกทางหนึ่งจุดรหัสเดียวในชุดอักขระ Unicode สามารถแมปกับลำดับไบต์ที่แตกต่างกันจริงขึ้นอยู่กับการเข้ารหัสที่ใช้สำหรับเอกสาร อักขระ Devanagari ที่มีรหัสจุด 2325 (ซึ่งคือ 915 ในรูปแบบเลขฐานสิบหก) จะถูกแทนด้วยสองไบต์เมื่อใช้การเข้ารหัส UTF-16 ( 09 15), สามไบต์ด้วย UTF-8 ( E0 A4 95) หรือสี่ไบต์ด้วย UTF-32 ( 00 00 09 15)

11

ชุดอักขระหรือชุดอักขระเป็นเพียงชุด (คอลเลกชันที่ไม่มีการเรียงลำดับ) ของอักขระ ชุดอักขระที่กำหนดรหัสกำหนดจำนวนเต็ม ("จุดรหัส") ให้กับอักขระแต่ละตัวในเพลง การเข้ารหัสเป็นวิธีการแทนจุดโค้ดอย่างไม่น่าสงสัยว่าเป็นสตรีมของไบต์


นี่ควรเป็นคำตอบที่ยอมรับได้ มันกำหนดแนวคิดที่ชัดเจนสามประการ: ชุดอักขระชุดอักขระที่เข้ารหัสและการเข้ารหัส
Marcus Junius Brutus

6

Googled สำหรับมัน http://en.wikipedia.org/wiki/Character_encoding

ความแตกต่างนั้นดูบอบบาง ชุดคำนั้นใช้ไม่ได้กับ Unicode Unicode ผ่านชุดของ abstractions อักขระที่เป็นนามธรรม -> จุดโค้ด -> การเข้ารหัสของจุดโค้ดเป็นไบต์

ชุดอักขระจะข้ามสิ่งนี้และข้ามจากอักขระไปยังไบต์โดยตรง ลำดับของไบต์ <-> ลำดับของอักขระ

ในระยะสั้นการเข้ารหัส: รหัสจุด -> ไบต์ charset: ตัวอักษร -> ไบต์


5

ชุดอักขระเป็นเพียงชุด มันมีทั้งเช่นสัญลักษณ์ยูโรหรืออื่น ๆ มันไม่ได้ นั่นคือทั้งหมดที่

การเข้ารหัสคือการทำแผนที่ bijective จากชุดอักขระเป็นชุดของจำนวนเต็ม หากรองรับเครื่องหมายยูโรนั้นจะต้องกำหนดจำนวนเต็มให้กับตัวละครนั้น ๆ


มันจะต้องมี Bijective หรือไม่?
Jörg W Mittag

2
การเข้ารหัสและถอดรหัสควรกำหนดขึ้นดังนั้นจึงไม่มีการแมปที่ไม่ชัดเจนใด ๆ ฉันคิดว่าคุณอาจมีจำนวนเต็มเป็นโคโดเมนที่ไม่ต่อเนื่องกัน แต่นั่นจะทำให้เปลืองเนื้อที่เมื่อคุณจัดเก็บข้อความและวิศวกรเกลียดพื้นที่ที่สูญเปล่า
Kilian Foth

1
การเข้ารหัสอักขระที่เป็นมรดกมักจะไม่ได้มีความหมายทางชีวภาพ ตัวอย่างเช่นใน IBM437 ทั้งßและβแสดงด้วย 0xE1
dan04

3

ในความคิดของฉันชุดอักขระเป็นส่วนหนึ่งของการเข้ารหัส (ส่วนประกอบ) การเข้ารหัสมีแอตทริบิวต์ชุดอักขระดังนั้นชุดอักขระสามารถใช้ในการเข้ารหัสได้หลายชุด ตัวอย่างเช่น unicode เป็นชุดอักขระที่ใช้ในการเข้ารหัสเช่น UTF-8, UTF-16 เป็นต้น ดูภาพประกอบที่นี่:ดูภาพประกอบที่นี่

ถ่านในชุดอักขระไม่ได้หมายถึงประเภทถ่านในโลกของการเขียนโปรแกรมมันหมายถึงถ่านในโลกแห่งความเป็นจริงในภาษาอังกฤษมันอาจจะเหมือนกัน แต่ในภาษาอื่นไม่เหมือนจีน '我' คือ 'ถ่าน' ในชุดอักขระ (UNICODE, GB [ใช้ใน GBK และ GB2312]) 'a' ยังเป็นอักขระในชุดอักขระ (ASCII, ISO-8859 , UNICODE)


1

ในความเห็นของฉันคำว่า "charset" ควรถูก จำกัด ให้ระบุพารามิเตอร์ที่ใช้ใน HTTP, MIME และมาตรฐานที่คล้ายกันเพื่อระบุการเข้ารหัสอักขระ (การแมปจากชุดอักขระข้อความไปยังลำดับไบต์) ตามชื่อ ตัวอย่างเช่นcharset=utf-8.

อย่างไรก็ตามฉันรู้ว่า MySQL, Java และสถานที่อื่น ๆ อาจใช้คำว่า "charset" เพื่อหมายถึงการเข้ารหัสอักขระ


1

การเข้ารหัสเป็นแมประหว่างไบต์และตัวอักษรจากชุดอักขระดังนั้นมันจะเป็นประโยชน์ในการหารือและเข้าใจความแตกต่างระหว่างระหว่างไบต์และตัวอักษร

คิดว่าไบต์เป็นตัวเลขระหว่าง 0 ถึง 255 ในขณะที่ตัวละครเป็นสิ่งที่เป็นนามธรรมเช่น "a", "1", "$" และ "Ä" ชุดของตัวละครทุกตัวที่มีอยู่จะเรียกว่าเป็นชุดตัวอักษร

อักขระแต่ละตัวมีลำดับหนึ่งหรือมากกว่าหนึ่งไบต์ที่ใช้เพื่อแสดง อย่างไรก็ตามจำนวนและค่าที่แน่นอนของไบต์ขึ้นอยู่กับการเข้ารหัสที่ใช้และมีการเข้ารหัสที่แตกต่างกันมากมาย

การเข้ารหัสส่วนใหญ่ขึ้นอยู่กับชุดอักขระเก่าและการเข้ารหัสที่เรียกว่า ASCII ซึ่งเป็นไบต์เดียวต่อตัวอักษร (จริง ๆ แล้วมีเพียง 7 บิต) และมีอักขระ 128 ตัวรวมถึงอักขระทั่วไปจำนวนมากที่ใช้ในภาษาอังกฤษแบบสหรัฐอเมริกา

ตัวอย่างเช่นต่อไปนี้คือ 6 อักขระในชุดอักขระ ASCII ที่แสดงด้วยค่า 60 ถึง 65

Extract of ASCII Table 60-65
╔══════╦══════════════╗
║ Byte ║  Character   ║
╠══════╬══════════════║
║  60  ║      <       ║
║  61  ║      =       ║
║  62  ║      >       ║
║  63  ║      ?       ║
║  64  ║      @       ║
║  65  ║      A       ║
╚══════╩══════════════╝

ในชุด ASCII เต็มรูปแบบค่าต่ำสุดที่ใช้คือศูนย์และสูงสุดคือ 127 (ทั้งคู่เป็นอักขระควบคุมที่ซ่อนอยู่)

อย่างไรก็ตามเมื่อคุณเริ่มต้องการตัวอักษรมากกว่า ASCII พื้นฐานที่มีให้ (เช่นตัวอักษรที่มีเครื่องหมายเน้นเสียงสัญลักษณ์สกุลเงินสัญลักษณ์กราฟิก ฯลฯ ) ASCII ไม่เหมาะและคุณต้องการบางสิ่งที่ครอบคลุมกว่า คุณต้องการอักขระเพิ่มขึ้น (ชุดอักขระที่แตกต่างกัน) และคุณต้องการการเข้ารหัสที่แตกต่างกันเนื่องจากอักขระ 128 ตัวนั้นไม่เพียงพอสำหรับตัวละครทุกตัวการเข้ารหัสบางตัวเสนอหนึ่งไบต์ (256 ตัวอักษร) หรือสูงสุดหกไบต์

เมื่อเวลาผ่านไปมีการสร้างการเข้ารหัสจำนวนมาก ในโลก Windows นั้นมี CP1252 หรือ ISO-8859-1 ในขณะที่ผู้ใช้ Linux มักจะชื่นชอบ UTF-8 Java ใช้ UTF-16 โดยกำเนิด

ลำดับของค่าไบต์สำหรับอักขระในการเข้ารหัสหนึ่งอาจแทนอักขระที่แตกต่างกันอย่างสมบูรณ์ในการเข้ารหัสอื่นหรืออาจไม่ถูกต้อง

ยกตัวอย่างเช่นในมาตรฐาน ISO 8859-1 , âเป็นตัวแทนจากหนึ่งไบต์ของมูลค่า226ในขณะที่ในUTF-8195, 162มันเป็นไบต์ที่สอง: อย่างไรก็ตามในมาตรฐาน ISO 8859-1 , 195, 162จะเป็นตัวละครทั้งสองเป็น¢

เมื่อคอมพิวเตอร์จัดเก็บข้อมูลเกี่ยวกับตัวละครภายในหรือส่งไปยังระบบอื่นพวกเขาจะจัดเก็บหรือส่งไบต์ 195, 162ลองนึกภาพระบบการเปิดไฟล์หรือรับข้อความเห็นไบต์ มันรู้ได้อย่างไรว่าตัวละครเหล่านี้คืออะไร?

เพื่อให้ระบบตีความไบต์เหล่านั้นเป็นอักขระจริง (และแสดงหรือแปลงเป็นการเข้ารหัสอื่น) จำเป็นต้องทราบการเข้ารหัสที่ใช้ นั่นคือเหตุผลที่การเข้ารหัสปรากฏในส่วนหัวของ XML หรือสามารถระบุในโปรแกรมแก้ไขข้อความ มันบอกระบบการทำแผนที่ระหว่างไบต์และตัวละคร

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