เรื่องวุ่น ๆ กับตัวหนังสือ – ตอนที่ 3 – Character Encoding

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

บทนี้จะพูดถึงเรื่อง Technical ล้วน ๆ ครับ ใครอยู่สายอื่นอาจจะไม่ต้องทำความเข่้าใจมันมากก็ได้ อันที่จริงมันไม่ค่อยมีประโยชน์ต่อคนในสาย Artist/Designer เท่าไหร่หรอก

String

ก่อนจะเข้าเรื่องการเข้ารหัส จะขอพูดถึง String ก่อน String ก็คือ สายอักขระ … สายของตัวอักษรนั่นล่ะ จริง ๆ ก็คือ ชุดของตัวอักษรที่เรียงต่อกันเป็นแนวยาว

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

ลักษณะพิเศษของ String ก็คือ มันเป็นข้อมูลแบบ Stream ที่ไหลไปทางเดียวกันตลอด จะสังเกตได้ว่าเวลาเราอ่านตัวหนังสือเราจะไม่ค่อยมีการอ่านย้อนกลับมากนัก (การอ่านข้อมูลในทิศทางเดียวเป็นลักษณะเฉพาะของ Stream) ดังนั้นเราจะมองว่า String คือ Stream ของ Character ก็ได้เหมือนกัน

Fixed-Length Character Encoding (การเข้ารหัสโดยใช้รหัสที่มีจำนวนหลักตายตัว)

การเข้ารหัสในลักษณะนี้จะเป็นการแทนที่ตัวอักษรใด ๆ ด้วยตัวเลขที่มีจำนวนหลัก (digit) แบบคงที่ เช่น การเข้่ารหัสด้วยตัวเลข 8หลัก (8บิท) 16หลัก หรือ 32 หลัก

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

ASCII และ Extended ASCII

ASCII เป็น การเข้ารหัสโดยใช้รหัสแบบ 8 บิท (หรือ 1ไบท์) โดยที่หลักสุดท้ายนั้นจะเป็น 0 เสมอ
โดยเราจะนับหลักหน่วย (หลักขวาสุด) เป็นหลักแรกนะครับ ดังนั้นจะมีจำนวนรหัสที่เป็นไปได้ทั้งหมดที่ 128 รหัส (ก็คือ 0-127 นั่นเอง) ASCII เป็นมาตรฐานที่รวบรวมเอาตัวอักษรและสัญลักษณ์ในภาษาอังกฤษ ซึ่งรวมถึงรหัสอักขระพิเศษที่ไม่ได้ใช้แสดงผลเอาไว้ด้วย (รหัสอักขระพิเศษ คือรหัสอักขระที่มีหน้าที่พิเศษ เช่น ตัดบรรทัด ขึ้นย่อหน้าใหม่ เป็นต้น เป็นอักขระที่ไม่ได้ใช้ในการแสดงผลครับ) ASCII เป็นมาตรฐานแรก ๆ ในโลกที่ยังคงใช้จนถึงปัจจุบันนี้ครับ

Extended ASCII เป็นการเพิ่มเติมส่วนขยายให้แก่ ASCII โดยจะมีการใช้ 1 บิทสุดท้าย (ที่ไม่ได้ใช้ใน ASCII) เพื่อเพิ่มจำนวนรหัสให้มากขึ้นเป็น 256 รหัส เพื่อที่จะเพิ่มรหัสสำหรับตัวอักษรที่ไม่ได้ใช้ในภาษาอังกฤษนั่นเองครับ

ตัวอย่างสำหรับมาตรฐาน Extended ASCII ก็เช่น ISO8859-1 (ชุดตัวอักษรลาติน) TIS620 (ชุดตัวอักษรภาษาไทย) เป็นต้น

UTF-16

UTF-16 เป็นมาตรฐานการเข้ารหัสที่กำหนดโดย Unicode เป็นการเข้ารหัสโดยการใช้รหัสตัวเลขที่ยาวถึง 16 หลัก (16บิท หรือ 2 ไบท์) ทำให้สามารถรองรับจำนวนรหัสได้ถึง 65,532 รหัสครับ ที่ต้องมากถึงขนาดนี้เพราะว่า Unicode เป็นมาตรฐานที่รวมเอารหัสของตัวอักษรในภาษาหลัก ๆ ที่ใช้กันในโลกนี้เอาไว้นั่นเอง

UTF-16 สามารถแบ่งย่อย ๆ ได้ตาม Endian ของมัน ก็คือ Big Endian และ Little Endian UTF16 แบบ Little Endian จะเรียกว่า UTF-16le ครับ ท่านที่่ไม่รู้ว่า endian คืออะไร ก็ขอความกรุณาศึกษาเพิ่มเติมเอาเองนะครับ

Variable-Length Character Encodeing (การเข้ารหัสโดยใช้รหัสที่มีจำนวนหลักไม่คงที่)

อันนี้ก็จะตรงกันข้าม ก็คือ รหัสแต่ละตัวอาจจะสั้นยาวไม่เท่ากัน ตามแต่ผู้ออกแบบกำหนด โดยส่วนใหญ่จะใช้วิธีกำหนดช่วงเอาไว้ว่า รหัสในช่วงใดช่วงนึงจะมีความยาวที่ระดับนึง ในขณะที่ในอีกช่วงนึงก็จะมีความยาวที่อีกระดับนึง เช่น ตัวอักษร 128 ตัวแรก ใช้รหัสที่ยาว 8 หลัก (8บิท หรือ 1 ไบท์) ในขณะที่ตัวที่เหลือจะใช้ความยาวที่ 16 หลัก (16 บิท หรือ 2 ไบท์) เป็นต้น

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

สามภาษาที่เป็นต้นเหตุของการเข้ารหัสแบบนี้นั้น เป็นประเทศในเอเซียตะวันออกทั้งหมดเลย นั่นคือ จีน ญี่ปุ่น และเกาหลี เราจะเรียกกลุ่มเประเทศเรื่องมากพวกนี้ว่า กลุ่ม CJK ครับ

ตัวอย่างของการเข้ารหัสแบบนี้ก็คือ BIG5 (Chinese), Shift-JIS(Japanese), EUC-KR (Korean) เป็นต้น ผมจะไม่พูดถึงรายละเอียดนะครับ แต่ลองค้นคว้ากันดูก็ได้นะ

UTF-8

UTF-8 เป็นการเข้ารหัสที่กำหนดโดย UNICODE เช่นเดียวกับ UTF-16 โดยการเข้ารหัสแบบนี้จะใช้รหัสที่สั้นที่สุดที่ 8 บิท (1ไบท์) จนถึงยาวที่สุดที่ 4ไบท์ โดยตัวที่จะบอกว่ารหัสนั้นยาวแค่ไหนก็คือบิทสุดท้ายของไบท์แรกที่อ่านครับ

  • ถ้าหลักสุดท้ายของไบท์แรก คือ 0 รหัสนี้จะยาว 8บิท
  • ถ้า 3 หลักสุดท้ายของไบท์แรก คือ 110 รหัสนี้จะยาว 16บิท
  • ถ้า 4 หลักสุดท้ายของไบท์แรก คือ 1110 รหัสนี้จะยาว 32บิท

โดยเราจะนับหลักหน่วย (หลักขวาสุด) เป็นหลักแรกนะครับ

แล้ว Encoding ประเภทไหนที่เราจะใช้ในเกมล่ะ ???

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

เมื่อนำทั้งสองตัวมาเปรียบเทียบกัน เราจะเห็นว่า

  • Fixed-Length เนี่ย ข้อดีคือ มันง่ายที่จะ Implement ครับ เพราะรหัสทุกตัวจะยาวเท่ากันหมด ส่วนข้อเสียคือมันใช้พื้นที่เยอะกว่าอีกแบบ
  • Variable-Length นั้น จะใช้พื้นที่น้อยกว่าครับ โดยเฉพาะถ้าเราเอาตัวอักษรที่ใช้บ่อยมาอยู่ในส่วนที่ใช้รหัสสั้น ๆ ได้ แต่ข้อเสียคือมันค่อนข้างลำบากกว่าที่จะ Implement

ดังนั้น ในเกม ซึ่งต้องการ Efficiency มาก ๆ เรามักจะใช้ Fixed-Length สำหรับการแสดงผล เพราะในระบบส่วนใหญ่จะมีหน่วยความจำมากเกินพอสำหรับการใช้งาน Encoding ประเภทนี้ครับ ในกรณีนี้การคำนวนที่เรียบง่ายนั้นเป็นสิ่งที่สำคัญกว่า และ Variable-Length จะใช้ในการส่งข้อมูลระหว่างเครื่องในเน็ทเวิร์ค เพราะขนาดของข้อมูลที่่รับส่งกันภายในเน็ทเวิร์คจะเล้กกว่า Fixed-length ทำให้รับส่งได้เร็วกว่าครับ

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *

This site uses Akismet to reduce spam. Learn how your comment data is processed.