Error – hexadecimal value 0x00, is an invalid character

Error – hexadecimal value 0x00, is an invalid character

ถ้าใช้คำสั่งแล้วมี error

C:\Users\Thada\Desktop\PolarUK\Xml>xsd Eval_Imperial.xsd /classes /language:CS /namespace:ncs2polaruk
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.8.3928.0]
Copyright (C) Microsoft Corporation. All rights reserved.
Error: ‘.’, hexadecimal value 0x00, is an invalid character. Line 2, position 1.

จาก error message ที่ได้รับ: Error: '.', hexadecimal value 0x00, is an invalid character. Line 2, position 1.
ปัญหานี้ชัดเจนมากครับ สาเหตุหลักมาจาก File Encoding ของไฟล์ Eval_Imperial.xsd ไม่ถูกต้อง
ตัว error hexadecimal value 0x00 หมายถึง อักขระ NULL (NULL character) ซึ่งเป็นอักขระที่ไม่สามารถแสดงผลได้และไม่ควรมีอยู่ในไฟล์ XML/XSD ครับ parser ของ xsd.exe ไปเจออักขระนี้เข้าที่ บรรทัดที่ 2 ตำแหน่งแรกสุด ก็เลยหยุดทำงานทันที
ปัญหานี้มักจะเกิดขึ้นเมื่อไฟล์ถูกบันทึกด้วย encoding ที่ไม่เข้ากัน เช่น UTF-16 หรือ UTF-32 แล้ว parser พยายามจะอ่านเป็น UTF-8 ทำให้เกิดการตีความ “Byte Order Mark” (BOM) ที่อยู่ต้นไฟล์ผิดพลาดกลายเป็นอักขระ NULL ครับ

หลักๆก็คือ ตอนสร้างไฟล์ XSD ด้วย xsd-gen มันใช้ Encoding = UTF-16 LE
ก็ไม่รู้ทำไมถึงต้องใช้ UTF-16
แต่ถ้าเราไม่ได้สังเกตุอะไร เวลาเปิดด้วย Text-Editor เราก็จะเห็นเป็นไฟล์ text ธรรมดา

แต่เวลาเราเขียนโปรแกรม มันจะอ่านมาทีละ byte หรือทีละแถว ทีนี้ถ้าเราไม่กำหนดว่า encoding คืออะไร เวลามันอ่านเข้ามามันก็อ่านมาไม่ครบ ถ้า UTF-8 มี 2 byte UTF-16 ก็จะเป็น 2 เท่า เวลาอ่านผิด codec มันก็อ่านมาไม่ครบตัวอักษร

UTF-16 LE คือ วิธีการเข้ารหัสตัวอักษร (Character Encoding) รูปแบบหนึ่ง ซึ่งสามารถแบ่งความหมายออกเป็น 2 ส่วนคือ:

  1. UTF-16: เป็นมาตรฐานการเข้ารหัสตัวอักษรในระบบ Unicode ที่ใช้พื้นที่อย่างน้อย 16 บิต (หรือ 2 ไบต์) ในการเก็บข้อมูลสำหรับตัวอักษร 1 ตัว ทำให้สามารถรองรับตัวอักษรได้หลากหลายภาษาทั่วโลก (มากกว่าแบบ ANSI หรือ TIS-620 ที่ใช้แค่ 1 ไบต์) เป็นรูปแบบที่ระบบปฏิบัติการ Windows ใช้เป็นหลักภายในระบบ
  2. LE (Little Endian): นี่คือส่วนที่สำคัญที่สุดและเป็นต้นตอของปัญหาที่คุณเจอครับ “Endian” หมายถึง “ลำดับของการจัดเก็บไบต์ (Byte Order)” สำหรับข้อมูลที่ใหญ่กว่า 1 ไบต์

หัวใจสำคัญ: Endianness (การเรียงลำดับไบต์) 💾

เมื่อคอมพิวเตอร์จะเก็บข้อมูลที่มีขนาด 2 ไบต์ (เช่น เลข 258 ซึ่งในเลขฐาน 16 คือ 0102) มันมีวิธีเก็บ 2 แบบ:

  • Big Endian (BE): “ใหญ่ไปเล็ก” คือเก็บไบต์ที่มีค่าสำคัญที่สุด (Most Significant Byte – MSB) ก่อน ตามด้วยไบต์ที่มีค่าน้อยกว่า
    • เลข 0x0102 จะถูกเก็บในหน่วยความจำเป็น 01 02 (ตรงไปตรงมาเหมือนที่คนอ่าน)
  • Little Endian (LE): “เล็กไปใหญ่” คือเก็บไบต์ที่มีค่าสำคัญน้อยที่สุด (Least Significant Byte – LSB) ก่อน แล้วค่อยตามด้วยไบต์ที่มีค่ามากกว่า
    • เลข 0x0102 จะถูกเก็บในหน่วยความจำเป็น 02 01 (สลับกัน)

สถาปัตยกรรมของ CPU ส่วนใหญ่ในปัจจุบัน (เช่น Intel, AMD) ใช้แบบ Little Endian ครับ

แล้วมันเกี่ยวกับ UTF-16 LE อย่างไร?

เมื่อเราจะเก็บตัวอักษรด้วย UTF-16 ซึ่งใช้ 2 ไบต์ ก็ต้องเลือกว่าจะเก็บแบบไหน

ตัวอย่าง: ตัวอักษร 'A' ใน Unicode คือ U+0041 ซึ่งมี 2 ไบต์คือ 00 และ 41

  • ถ้าเก็บแบบ UTF-16 BE (Big Endian) จะเก็บเป็น: 00 41
  • ถ้าเก็บแบบ UTF-16 LE (Little Endian) จะเก็บเป็น: 41 00

สาเหตุของ Error ที่คุณเจอ

ไฟล์ที่บันทึกเป็น UTF-16 มักจะมีอักขระพิเศษ 2 ไบต์นำหน้าไฟล์ที่เรียกว่า Byte Order Mark (BOM) เพื่อบอกให้โปรแกรมที่มาเปิดไฟล์รู้ว่าควรจะอ่านไบต์แบบไหน

  • UTF-16 LE จะมี BOM เป็น FF FE
  • UTF-16 BE จะมี BOM เป็น FE FF

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *