ความแตกต่างระหว่าง UTF-8 และ UTF-8 ที่ไม่มี BOM คืออะไร


818

มีอะไรที่แตกต่างกันระหว่าง UTF-8 และ UTF-8 โดยไม่ต้องBOM ? ไหนดีกว่ากัน


77
UTF-8 สามารถตรวจจับอัตโนมัติได้ดีกว่าโดยเนื้อหากว่าโดย BOM วิธีการง่าย: พยายามอ่านไฟล์ (หรือสตริง) เป็น UTF-8 และหากประสบความสำเร็จสมมติว่าข้อมูลเป็น UTF-8 มิฉะนั้นสมมติว่าเป็น CP1252 (หรือการเข้ารหัส 8 บิตอื่น ๆ ) การเข้ารหัสแปดบิตที่ไม่ใช่ UTF-8 ใด ๆ จะมีลำดับที่แทบจะไม่ได้รับอนุญาตจาก UTF-8 Pure ASCII (7 บิต) ถูกตีความว่าเป็น UTF-8 แต่ผลลัพธ์ก็ถูกต้องเช่นกัน
Tronic

39
การสแกนไฟล์ขนาดใหญ่สำหรับเนื้อหา UTF-8 ต้องใช้เวลา BOM ทำให้กระบวนการนี้เร็วขึ้นมาก ในทางปฏิบัติคุณมักจะต้องทำทั้งสองอย่าง ผู้ร้ายในปัจจุบันคือยังมีเนื้อหาข้อความจำนวนมากไม่ใช่ Unicode และฉันยังคงชนกับเครื่องมือที่บอกว่าพวกเขาทำ Unicode (เช่น UTF-8) แต่ปล่อยเนื้อหาที่แตกต่างออกไป
Jeroen Wiert Pluimers

10
@Tronic ฉันไม่คิดว่า"ดีกว่า"เหมาะสมในกรณีนี้ มันขึ้นอยู่กับสภาพแวดล้อม หากคุณแน่ใจว่าไฟล์ UTF-8 ทั้งหมดถูกทำเครื่องหมายด้วยBOMมากกว่าการตรวจสอบBOMเป็นวิธีที่"ดีกว่า"เพราะมันเร็วกว่าและเชื่อถือได้มากกว่า
mg30rg

32
UTF-8 ไม่มี BOM เมื่อคุณใส่จุดรหัส U + FEFF ที่จุดเริ่มต้นของไฟล์ UTF-8 ต้องระมัดระวังเป็นพิเศษในการจัดการกับมัน นี่เป็นเพียงหนึ่งในการตั้งชื่อของ Microsoft เช่นการเรียกการเข้ารหัส "Unicode" เมื่อไม่มีสิ่งนั้น
tchrist

7
"เมนเฟรมอันทันสมัย ​​(และ AIX) นั้นเป็น endian เล็ก ๆ น้อย ๆ ที่รู้เรื่อง UTF-8 " UTF-8 ไม่มีความสิ้นสุด ! ไม่มีการสับไบต์เพื่อวางคู่หรือกลุ่มสี่ลงใน "คำสั่ง" ที่ถูกต้องสำหรับระบบเฉพาะ! ในการตรวจจับลำดับ UTF-8 อาจเป็นประโยชน์ที่จะต้องทราบว่าไบต์แรกของลำดับหลายไบต์ "codepoint" (ไบต์ที่ไม่ใช่ ASCII "ธรรมดา") มีชุดบิต MS และอีกหนึ่งถึงสามเพิ่มเติม บิตที่มีนัยสำคัญน้อยกว่าอย่างต่อเนื่องตามด้วยบิตรีเซ็ต จำนวนของผู้ที่ชุดบิตเป็นหนึ่งไบต์น้อยที่อยู่ในจุดโค้ดที่และพวกเขาทั้งหมดจะมีชุด MSB ...
SlySven

คำตอบ:


773

UTF-8 BOM เป็นลำดับของไบต์ที่จุดเริ่มต้นของสตรีมข้อความ ( 0xEF, 0xBB, 0xBF) ที่ช่วยให้ผู้อ่านเดาไฟล์ได้อย่างน่าเชื่อถือมากขึ้นว่าเข้ารหัสใน UTF-8

โดยปกติBOMจะใช้เพื่อส่งสัญญาณความเป็นendiannessของการเข้ารหัส แต่เนื่องจาก endianness นั้นไม่เกี่ยวข้องกับ UTF-8 จึงไม่จำเป็นต้องใช้ BOM

ตามที่มาตรฐาน Unicodeที่BOM สำหรับไฟล์ UTF-8 จะไม่แนะนำ :

2.6 แผนการเข้ารหัส

... ไม่จำเป็นต้องใช้ BOM หรือแนะนำสำหรับ UTF-8 แต่อาจพบในบริบทที่ข้อมูล UTF-8 ถูกแปลงจากรูปแบบการเข้ารหัสอื่น ๆ ที่ใช้ BOM หรือที่ BOM ใช้เป็นลายเซ็น UTF-8 . ดูส่วนย่อย“ Byte Order Mark” ในส่วน 16.8 พิเศษสำหรับข้อมูลเพิ่มเติม


114
อาจไม่แนะนำ แต่จากประสบการณ์ของฉันในการแปลงภาษาฮิบรูบางครั้ง BOM มีความสำคัญต่อการจดจำ UTF-8 ใน Excel และอาจสร้างความแตกต่างระหว่าง Jibrish และภาษาฮิบรู
Matanya

26
อาจไม่ได้รับการแนะนำ แต่ได้ทำสิ่งมหัศจรรย์กับสคริปต์ powershell ของฉันเมื่อพยายามที่จะแสดงผล "æøå"
Marius

63
ไม่ว่ามันจะไม่ได้รับการแนะนำโดยมาตรฐานก็ตามมันก็อนุญาตและฉันชอบที่มีบางอย่างที่ทำหน้าที่เป็นลายเซ็น UTF-8 แทนที่จะเป็นทางเลือกในการเดาหรือคาดเดา ซอฟต์แวร์ที่สอดคล้องกับ Unicode ควร / ต้องสามารถจัดการกับการมีอยู่ของมันได้ดังนั้นฉันจึงสนับสนุนให้ใช้เป็นการส่วนตัว
martineau

30
@ bames53: ใช่ในโลกอุดมคติที่จัดเก็บการเข้ารหัสไฟล์ข้อความเนื่องจากข้อมูลเมตาของระบบไฟล์จะเป็นวิธีที่ดีกว่าในการเก็บรักษาไว้ แต่พวกเราส่วนใหญ่ที่อาศัยอยู่ในโลกแห่งความเป็นจริงไม่สามารถเปลี่ยนระบบไฟล์ของระบบปฏิบัติการที่โปรแกรมของเราทำงานได้ดังนั้นการใช้ลายเซ็น BOM ที่ไม่ขึ้นกับแพลตฟอร์มของ Unicode มาตรฐานดูเหมือนว่าเป็น IMHO ทางเลือกที่ดีที่สุด
martineau

34
@ Martineau เมื่อวานนี้ฉันพบไฟล์ที่มี UTF-8 BOM ซึ่งไม่ใช่ UTF-8 (นั่นคือ CP936) สิ่งที่โชคร้ายก็คือคนที่รับผิดชอบต่อปริมาณความเจ็บปวดที่เกิดจาก UTF-8 BOM นั้นส่วนใหญ่จะไม่สนใจมัน
bames53

243

คำตอบที่ยอดเยี่ยมอื่น ๆ ตอบแล้วว่า:

  • ไม่มีความแตกต่างอย่างเป็นทางการระหว่าง UTF-8 และ BOM-ed UTF-8
  • สตริง BOM-ed UTF-8 จะเริ่มต้นด้วยสามไบต์ต่อไปนี้ EF BB BF
  • ไบต์เหล่านั้นถ้ามีจะต้องถูกละเว้นเมื่อทำการแยกสตริงออกจากไฟล์ / สตรีม

แต่เนื่องจากข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ BOM สำหรับ UTF-8 อาจเป็นวิธีที่ดีในการ "ดม" ถ้าสตริงถูกเข้ารหัสใน UTF-8 ... หรืออาจเป็นสตริงที่ถูกต้องในการเข้ารหัสอื่น ๆ ...

ตัวอย่างเช่นข้อมูล [EF BB BF 41 42 43] อาจเป็น:

  • สตริงISO-8859-1 ที่ถูกต้องตามกฎหมาย" ABC"
  • สตริงUTF-8 ที่ถูกต้องตามกฎหมาย"ABC"

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

การเข้ารหัสควรเป็นที่รู้จักไม่ใช่การทำนาย


60
@Alcott: คุณเข้าใจถูกต้อง สตริง [EF BB BF 41 42 43] เป็นเพียงจำนวนไบต์ คุณต้องการข้อมูลภายนอกเพื่อเลือกวิธีการตีความ หากคุณเชื่อว่าไบต์เหล่านั้นถูกเข้ารหัสโดยใช้ ISO-8859-1 สตริงนั้นคือ " ABC" หากคุณเชื่อว่าไบต์เหล่านั้นถูกเข้ารหัสโดยใช้ UTF-8 แสดงว่าเป็น "ABC" หากคุณไม่รู้คุณต้องพยายามค้นหา BOM อาจเป็นเบาะแส การไม่มีอักขระที่ไม่ถูกต้องเมื่อถอดรหัสเป็น UTF-8 อาจเป็นอีกอย่างหนึ่ง ... ในท้ายที่สุดถ้าคุณไม่สามารถจดจำ / ค้นหาการเข้ารหัสอย่างใดอาร์เรย์ของไบต์เป็นเพียงอาร์เรย์ของไบต์
paercebal

19
@ paercebal ในขณะที่ "" ถูกต้อง latin-1 มันเป็นไปได้ยากมากที่ไฟล์ข้อความขึ้นต้นด้วยชุดค่าผสมนั้น การถือครองเดียวกันสำหรับเครื่องหมาย ucs2-le / be ÿþและþÿ นอกจากนี้คุณไม่สามารถรู้
user877329

16
@deceze มันอาจเป็นภาษาที่ไม่ถูกต้อง: First ï (ซึ่งก็โอเค) จากนั้นก็มีเครื่องหมายคำพูดบางคำที่ไม่มีช่องว่างระหว่าง (ไม่ตกลง) ¿ระบุว่าเป็นภาษาสเปน แต่ไม่ได้ใช้ในภาษาสเปน สรุป: มันไม่ใช่ละติน -1 ที่มีความมั่นใจสูงกว่าความเชื่อมั่นที่ไม่มีมัน
user877329

20
@ ผู้ใช้แน่นอนมันไม่จำเป็นต้องสมเหตุสมผล แต่ถ้าระบบของคุณขึ้นอยู่กับการคาดเดานั่นคือสิ่งที่ไม่แน่นอนผู้ใช้ที่เป็นอันตรายบางคนส่งข้อความที่เริ่มต้นด้วยตัวอักษร 3 ตัวโดยมีจุดประสงค์และระบบของคุณสมมติว่ากำลังมองหา UTF-8 ด้วย BOM มันควรใช้ Latin-1 และการฉีด Unicode บางอย่างก็เกิดขึ้น เป็นเพียงตัวอย่างสมมุติ แต่เป็นไปได้อย่างแน่นอน คุณไม่สามารถตัดสินการเข้ารหัสข้อความตามระยะเวลา
หลอกลวง

40
"การเข้ารหัสควรเป็นที่รู้จักไม่ใช่การทำนาย" หัวใจและจิตวิญญาณของปัญหา +1 ท่านดี กล่าวอีกนัยหนึ่ง: ทำให้เนื้อหาของคุณเป็นมาตรฐานและพูดว่า "เราใช้การเข้ารหัสนี้เป็นช่วงเวลาเสมอเขียนวิธีนั้นอ่านวิธีนั้น" หรือพัฒนารูปแบบเพิ่มเติมที่ช่วยให้สามารถจัดเก็บการเข้ารหัสเป็นเมทาดาทา (ส่วนหลังอาจต้องการ "การเข้ารหัสมาตรฐาน bootstrap" เช่นกันเช่นการพูดว่า "ส่วนที่บอกการเข้ารหัสเสมอ ASCII")
jpmc26

135

มีปัญหาอย่างน้อยสามข้อในการใส่ BOM ในไฟล์ที่เข้ารหัส UTF-8

  1. ไฟล์ที่ไม่มีข้อความจะไม่ว่างเปล่าเนื่องจากไฟล์เหล่านั้นมี BOM อยู่เสมอ
  2. ไฟล์ที่เก็บข้อความที่อยู่ในชุดย่อยของ ASCII ของ UTF-8 นั้นไม่ได้เป็นตัวเองอีกต่อไปเพราะ ASCII เพราะ BOM ไม่ใช่ ASCII ซึ่งทำให้เครื่องมือที่มีอยู่บางส่วนพังลงและเป็นไปไม่ได้ที่ผู้ใช้จะเปลี่ยนเครื่องมือดั้งเดิม
  3. ไม่สามารถต่อกันหลายไฟล์เข้าด้วยกันเพราะตอนนี้แต่ละไฟล์มี BOM อยู่ในตอนเริ่มต้น

และอย่างที่คนอื่น ๆ พูดถึงมันไม่เพียงพอหรือไม่จำเป็นที่จะต้องมี BOM เพื่อตรวจสอบว่ามีบางอย่างที่เป็น UTF-8:

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

8
จุดที่ 1 "ไฟล์ที่ไม่มีข้อความจะไม่ว่างเปล่าอีกต่อไปเพราะมันมี BOM อยู่เสมอ" ซึ่งนี่ (1) ทำให้ระดับระบบไฟล์ของระบบปฏิบัติการ OS เป็นระดับเนื้อหาที่ถูกตีความรวมถึง (2) ถือว่าไม่ถูกต้อง BOM ยังอยู่ในไฟล์ว่างทุกอย่างเป็นอย่างอื่น วิธีแก้ปัญหาในทางปฏิบัติเพื่อ (1) คือไม่ทำ (2) โดยพื้นฐานแล้วการร้องเรียนจะลดลงไปที่ "เป็นไปได้ที่จะนำ BOM ไปใส่ในไฟล์ที่ว่างเปล่าเป็นอย่างอื่นดังนั้นจึงป้องกันการตรวจจับไฟล์ที่ว่างเปล่าทางตรรกะได้ง่ายที่สุด (โดยการตรวจสอบขนาดไฟล์)" ยังดีซอฟต์แวร์ควรสามารถจัดการกับมันเนื่องจากมีวัตถุประสงค์
ไชโยและ hth - Alf

7
จุดที่ 2 "ไฟล์ที่มีข้อความ ASCII ไม่ใช่ ASCII อีกต่อไป" ซึ่งจะทำให้ ASCII ใช้ UTF-8 ได้ ไฟล์ UTF-8 ที่เก็บข้อความ ASCII ไม่ใช่ ASCII มันเป็น UTF-8 ในทำนองเดียวกันไฟล์ UTF-16 ที่เก็บข้อความ ASCII ไม่ใช่ ASCII แต่เป็น UTF-16 และอื่น ๆ ASCII เป็นรหัสไบต์เดียว 7 บิต UTF-8 เป็นส่วนขยายความยาวผันแปร 8 บิตของ ASCII หาก "เครื่องมือแยกย่อย" เนื่องจาก> 127 ค่าแสดงว่ามันไม่เหมาะกับโลก 8 บิต วิธีแก้ปัญหาเชิงปฏิบัติอย่างง่ายอย่างหนึ่งคือการใช้เฉพาะไฟล์ ASCII กับเครื่องมือที่แยกย่อยสำหรับค่าไบต์ที่ไม่ใช่ ASCII ทางออกที่ดีกว่าคือการทิ้งเครื่องมือที่ไม่ดีเหล่านั้น
ไชโยและ hth - Alf

8
Re ชี้ 3, "มันเป็นไปไม่ได้ที่จะต่อกันหลาย ๆ ไฟล์เข้าด้วยกันเพราะตอนนี้แต่ละไฟล์มี BOM ตอนเริ่มต้น" ผิด ฉันไม่มีปัญหาการเชื่อมโยงไฟล์ UTF-8 กับ BOM ดังนั้นจึงเป็นไปได้อย่างชัดเจน ฉันคิดว่าบางทีคุณหมายถึง Unix-land catจะไม่ให้ผลลัพธ์ที่สะอาดผลลัพธ์ที่มี BOM ในช่วงเริ่มต้นเท่านั้น ถ้าคุณหมายถึงอย่างนั้นนั่นเป็นเพราะการcatทำงานในระดับไบต์ไม่ใช่ระดับเนื้อหาที่ถูกตีความและในทำนองเดียวกันcatไม่สามารถจัดการภาพถ่ายได้ ถึงกระนั้นมันก็ไม่ได้ทำอันตรายอะไรมากมาย นั่นเป็นเพราะ BOM เข้ารหัสพื้นที่ไม่ทำลายความกว้างเป็นศูนย์
ไชโยและ hth - Alf

20
@ Cheersandhth. -Alf คำตอบนี้ถูกต้อง คุณแค่ชี้ให้เห็นข้อบกพร่องของ Microsoft
tchrist

9
@brighty: สถานการณ์ไม่ดีขึ้นโดยการเพิ่ม bom
Deduplicator

84

นี่คือตัวอย่างของการใช้ BOM ที่ทำให้เกิดปัญหาจริงและยังมีอีกหลายคนที่ไม่รู้

BOM แบ่งสคริปต์

สคริปต์ Shell, สคริปต์ Perl, สคริปต์ Python, สคริปต์ Ruby, สคริปต์ Node.js หรือปฏิบัติการอื่นใดที่จำเป็นต้องเรียกใช้โดยล่าม - เริ่มต้นด้วยบรรทัด shebangซึ่งมีลักษณะดังนี้:

#!/bin/sh
#!/usr/bin/python
#!/usr/local/bin/perl
#!/usr/bin/env node

มันบอกระบบที่ต้องใช้ล่ามเมื่อเรียกใช้สคริปต์ดังกล่าว หากสคริปต์ถูกเข้ารหัสใน UTF-8 อาจมีการล่อลวงให้รวม BOM ตั้งแต่เริ่มต้น แต่จริงๆแล้ว "#!" ตัวละครไม่ได้เป็นเพียงตัวละคร ในความเป็นจริงแล้วพวกเขาเป็นเลขอาถรรพ์ที่ประกอบด้วยตัวละคร ASCII สองตัว หากคุณใส่บางสิ่ง (เช่น BOM) ไว้หน้าอักขระเหล่านั้นไฟล์จะดูเหมือนว่ามีหมายเลขเวทย์มนตร์แตกต่างกันและอาจนำไปสู่ปัญหาได้

ดู Wikipedia, บทความ: Shebang, หมวด: Magic number :

อักขระ shebang นั้นมีสองไบต์เดียวกันในการเข้ารหัส ASCII แบบขยายรวมถึง UTF-8 ซึ่งโดยทั่วไปจะใช้สำหรับสคริปต์และไฟล์ข้อความอื่น ๆ บนระบบ Unix ที่คล้ายกันในปัจจุบัน อย่างไรก็ตามไฟล์ UTF-8 อาจเริ่มต้นด้วยเครื่องหมายสั่งทางเลือก (BOM); หากฟังก์ชั่น "exec" ตรวจพบไบต์ 0x23 และ 0x21 โดยเฉพาะการแสดงตนของ BOM (0xEF 0xBB 0xBF) ก่อนที่ shebang จะป้องกันไม่ให้ล่ามสคริปต์ทำงานผู้มีอำนาจบางคนแนะนำให้ต่อต้านการใช้เครื่องหมายคำสั่งไบต์ในสคริปต์ POSIX (เหมือน Unix), [14] ด้วยเหตุผลนี้และสำหรับการทำงานร่วมกันที่กว้างขึ้นและข้อกังวลทางปรัชญา นอกจากนี้ไม่จำเป็นต้องใช้เครื่องหมายคำสั่งไบต์ใน UTF-8 เนื่องจากการเข้ารหัสนั้นไม่มีปัญหาเรื่องความเอนเอียง มันทำหน้าที่เพียงเพื่อระบุการเข้ารหัสเป็น UTF-8 [เน้นเพิ่ม]

BOM ผิดกฎหมายใน JSON

ดูRFC 7159, ส่วนที่ 8.1 :

การนำไปใช้งานต้องไม่เพิ่มเครื่องหมายคำสั่งไบต์ไปยังจุดเริ่มต้นของข้อความ JSON

BOM ซ้ำซ้อนใน JSON

ไม่เพียง แต่เป็นสิ่งผิดกฎหมายใน JSON เท่านั้นยังไม่จำเป็นต้องพิจารณาการเข้ารหัสอักขระเนื่องจากมีวิธีที่เชื่อถือได้มากกว่าในการกำหนดการเข้ารหัสอักขระและ endianness ที่ใช้ในสตรีม JSON ใด ๆ อย่างไม่น่าสงสัย (ดูคำตอบนี้สำหรับรายละเอียด)

BOM แบ่งตัวแยกวิเคราะห์ JSON

ไม่เพียง แต่เป็นสิ่งผิดกฎหมายใน JSON และไม่จำเป็นแต่อย่างใดมันแตกซอฟต์แวร์ทั้งหมดที่กำหนดการเข้ารหัสโดยใช้วิธีการนำเสนอในRFC 4627 :

การพิจารณาการเข้ารหัสและ endianness ของ JSON ตรวจสอบสี่ไบต์แรกสำหรับไบต์ NUL:

00 00 00 xx - UTF-32BE
00 xx 00 xx - UTF-16BE
xx 00 00 00 - UTF-32LE
xx 00 xx 00 - UTF-16LE
xx xx xx xx - UTF-8

ตอนนี้ถ้าไฟล์เริ่มต้นด้วย BOM มันจะมีลักษณะดังนี้:

00 00 FE FF - UTF-32BE
FE FF 00 xx - UTF-16BE
FF FE 00 00 - UTF-32LE
FF FE xx 00 - UTF-16LE
EF BB BF xx - UTF-8

โปรดทราบว่า:

  1. UTF-32BE ไม่ได้เริ่มต้นด้วย NUL สามตัวดังนั้นจึงไม่เป็นที่รู้จัก
  2. UTF-32LE ไบต์แรกไม่ได้ตามด้วย NUL สามตัวดังนั้นจะไม่ถูกจดจำ
  3. UTF-16BE มีเพียง NUL เดียวในสี่ไบต์แรกดังนั้นจึงไม่เป็นที่รู้จัก
  4. UTF-16LE มีเพียง NUL เดียวในสี่ไบต์แรกดังนั้นจึงไม่เป็นที่รู้จัก

ทั้งหมดอาจถูกตีความอย่างไม่ถูกต้องว่าเป็น UTF-8 และตีความผิดหรือปฏิเสธว่าเป็น UTF-8 ที่ไม่ถูกต้องหรือไม่ได้รับการยอมรับ

นอกจากนี้หากการทดสอบการใช้งานสำหรับ JSON ที่ถูกต้องตามที่ฉันแนะนำมันจะปฏิเสธแม้กระทั่งอินพุตที่เข้ารหัสแน่นอนเป็น UTF-8 เพราะมันไม่ได้ขึ้นต้นด้วยอักขระ ASCII <128 เท่าที่ควรเป็นไปตาม RFC

รูปแบบข้อมูลอื่น ๆ

ไม่จำเป็นต้องใช้ BOM ใน JSON ถือเป็นการกระทำที่ผิดกฎหมายและทำลายซอฟต์แวร์ที่ทำงานอย่างถูกต้องตาม RFC มันควรจะเป็นผู้ดีที่ไม่ใช้แล้วและยังมีคนที่ยืนยันในการทำลาย JSON โดยใช้ BOM ความคิดเห็นกฎการอ้างอิงที่แตกต่างกันหรือประเภทข้อมูลที่แตกต่างกันเสมอ แน่นอนว่าทุกคนมีอิสระที่จะใช้สิ่งต่าง ๆ เช่น BOM หรืออะไรก็ได้ถ้าคุณต้องการ - อย่าเรียกมันว่า JSON

สำหรับรูปแบบข้อมูลอื่นที่ไม่ใช่ JSON ลองดูว่ามันมีลักษณะอย่างไร หากการเข้ารหัสเพียงอย่างเดียวคือ UTF- * และอักขระตัวแรกจะต้องเป็นอักขระ ASCII ที่ต่ำกว่า 128 ดังนั้นคุณจึงมีข้อมูลทั้งหมดที่จำเป็นในการพิจารณาการเข้ารหัสและความสิ้นสุดของข้อมูลของคุณ การเพิ่ม BOMs แม้จะเป็นคุณลักษณะเสริมจะทำให้ซับซ้อนและเกิดข้อผิดพลาดได้ง่ายขึ้นเท่านั้น

การใช้ BOM อื่น ๆ

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


5
rfc7159 ซึ่งแทนที่ rfc4627 จริง ๆ แล้วแนะนำ BOM ที่สนับสนุนอาจไม่เลวร้ายนัก โดยทั่วไปแล้วการไม่มี BOM เป็นเพียง kludge ที่คลุมเครือเพื่อให้ซอฟต์แวร์ Windows และ Unix รุ่นเก่าที่ไม่ได้ใช้ Unicode ที่ทราบสามารถประมวลผล utf-8 ได้
Eric Grange

2
เสียงเหมือน JSON ต้องการการอัปเดตเพื่อรองรับเช่นเดียวกับสคริปต์ Perl, สคริปต์ Python, สคริปต์ Ruby, Node.js เพียงเพราะแพลตฟอร์มเหล่านี้เลือกที่จะไม่รวมการสนับสนุนไม่จำเป็นต้องฆ่า BOM Apple พยายามฆ่า Adobe มาหลายปีแล้วและ Adobe ยังอยู่ แต่โพสต์ enlightening
htm11h

13
@EricGrange ดูเหมือนว่าคุณจะสนับสนุน BOM อย่างมาก แต่ล้มเหลวที่จะรู้ว่าสิ่งนี้จะทำให้รูปแบบ "ข้อความธรรมดา" ที่แพร่หลายมีประโยชน์และมีประโยชน์ในระดับสากลซึ่งเป็นรูปแบบที่ดีที่สุดของอดีต UTF8 ก่อน! การเพิ่มส่วนหัว (in-band) ใด ๆ ลงในสตรีมข้อความธรรมดาโดยนิยามจะกำหนดโปรโตคอลบังคับให้กับไฟล์ข้อความที่ง่ายที่สุดทำให้ไม่เป็น "ง่าย" อีกต่อไป! และเพื่อประโยชน์อะไร เพื่อสนับสนุนทั้งหมดอื่น ๆ , การเข้ารหัส CP โบราณที่ยังไม่ได้มีลายเซ็นดังนั้นคุณอาจเข้าใจผิดว่าด้วย UTF-8? (BTW, ASCII คือ UTF-8 เช่นกันดังนั้น BOM สำหรับพวกนั้นด้วย?;) มาเลย)
Sz

2
คำตอบนี้คือเหตุผลที่ฉันมาถึงคำถามนี้! ฉันสร้างสคริปต์ทุบตีใน Windows และพบปัญหามากมายเมื่อเผยแพร่สคริปต์เหล่านั้นไปยัง Linux! สิ่งเดียวกันกับไฟล์ jason
Tono Nam

2
ฉันหวังว่าฉันจะโหวตคำตอบนี้ได้ประมาณห้าสิบครั้ง ฉันต้องการเพิ่มว่า ณ จุดนี้ UTF-8 ชนะสงครามมาตรฐานและข้อความเกือบทั้งหมดที่ผลิตบนอินเทอร์เน็ตคือ UTF-8 ภาษาการเขียนโปรแกรมยอดนิยมบางภาษา (เช่น C # และ Java) ใช้ UTF-16 ภายใน แต่เมื่อโปรแกรมเมอร์ที่ใช้ภาษาเหล่านั้นเขียนไฟล์ลงในเอาต์พุตสตรีมพวกเขามักจะเข้ารหัสเป็น UTF-8 ดังนั้นจึงไม่มีเหตุผลที่จะมี BOM เพื่อทำเครื่องหมายไฟล์ UTF-8 อีกต่อไป UTF-8 ควรเป็นค่าเริ่มต้นที่คุณใช้เมื่ออ่านและลองเข้ารหัสอื่น ๆ หากการถอดรหัส UTF-8 ล้มเหลว
rmunn

51

อะไรคือความแตกต่างระหว่าง UTF-8 และ UTF-8 ที่ไม่มี BOM

คำตอบสั้น ๆ : ใน UTF-8 BOM จะถูกเข้ารหัสเป็นไบต์EF BB BFที่จุดเริ่มต้นของไฟล์

คำตอบยาว:

เริ่มแรกคาดว่าUnicodeจะถูกเข้ารหัสใน UTF-16 / UCS-2 BOM ได้รับการออกแบบสำหรับรูปแบบการเข้ารหัสนี้ เมื่อคุณมีหน่วยรหัส 2 ไบต์คุณจำเป็นต้องระบุลำดับที่สองไบต์นั้นและแบบแผนทั่วไปสำหรับการทำเช่นนี้คือการรวมอักขระ U + FEFF เป็น "เครื่องหมายคำสั่งซื้อ Byte" ที่จุดเริ่มต้นของข้อมูล อักขระ U + FFFE ถูกยกเลิกการกำหนดอย่างถาวรเพื่อให้สามารถใช้การตรวจสอบลำดับไบต์ที่ไม่ถูกต้องได้

UTF-8 มีลำดับไบต์เดียวกันโดยไม่คำนึงถึงแพลตฟอร์ม endianness ดังนั้นจึงไม่จำเป็นต้องมีเครื่องหมายใบสั่งไบต์ อย่างไรก็ตามอาจเกิดขึ้น (ตามลำดับไบต์EF BB FF) ในข้อมูลที่ถูกแปลงเป็น UTF-8 จาก UTF-16 หรือเป็น "ลายเซ็น" เพื่อระบุว่าข้อมูลนั้นเป็น UTF-8

ไหนดีกว่ากัน

ไม่มี ตามที่ Cote มาร์ตินตอบมาตรฐาน Unicode ไม่แนะนำ มันทำให้เกิดปัญหากับซอฟต์แวร์ที่ไม่ใช่ BOM

วิธีที่ดีกว่าในการตรวจสอบว่าไฟล์เป็น UTF-8 คือการตรวจสอบความถูกต้องหรือไม่ UTF-8 มีกฎที่เข้มงวดเกี่ยวกับลำดับของไบต์ที่ถูกต้องดังนั้นความน่าจะเป็นของการบวกที่ผิดพลาดจึงไม่มีความสำคัญ หากลำดับไบต์ดูเหมือนว่า UTF-8 ก็น่าจะเป็น


8
สิ่งนี้จะทำให้โมฆะ UTF-8 ที่ใช้งานไม่ได้นั้นมีไบต์ที่ผิดพลาดเพียงตัวเดียวในนั้นแม้ว่า: /
endolith

8
-1 อีกครั้ง "มันทำให้เกิดปัญหากับซอฟต์แวร์ที่ไม่ได้รับรู้ BOM" นั่นไม่เคยเป็นปัญหาสำหรับฉัน แต่ในทางตรงกันข้ามการที่ไม่มี BOM นั้นทำให้เกิดปัญหากับซอฟต์แวร์ที่รับรู้ BOM (โดยเฉพาะอย่างยิ่ง Visual C ++) ปัญหา. ดังนั้นคำสั่งนี้เป็นแพลตฟอร์มที่เฉพาะเจาะจงมากมุมมอง Unix-land ที่แคบ แต่มีการนำเสนอที่เข้าใจผิดราวกับว่ามันใช้โดยทั่วไป ซึ่งมันไม่ได้
ไชโยและ hth - Alf

6
ไม่ UTF-8 ไม่มี BOM คำตอบนี้ไม่ถูกต้อง ดูมาตรฐาน Unicode
tchrist

2
คุณสามารถคิดได้ว่าคุณมีไฟล์ ASCII แท้ๆเมื่อมองไปที่ไบต์ แต่นี่อาจเป็นไฟล์ utf-16 เช่นกันที่คุณต้องดูคำศัพท์และไม่ต้องเป็นไบต์ ซอฟต์แวร์สมัยใหม่ควรทราบเกี่ยวกับ BOM การอ่าน utf-8 อาจล้มเหลวหากตรวจพบลำดับที่ไม่ถูกต้อง codepoint ที่สามารถใช้ลำดับที่เล็กกว่าหรือ codepoints ที่เป็นตัวแทน สำหรับการอ่าน utf-16 อาจล้มเหลวเช่นกันเมื่อมีตัวแทนอุ้มเด็กกำพร้า
brighty

1
@ อัลฉันไม่เห็นด้วยกับการตีความทัศนคติที่ไม่ใช่ BOM ของคุณว่า " เฉพาะแพลตฟอร์มซึ่งเป็นมุมมอง Unix-land ที่แคบ" สำหรับฉันวิธีเดียวที่ความคิดแบบแคบ ๆ อาจอยู่กับ "Unix land" ก็คือถ้า MS และ Visual C ++ มาก่อน * NIX ซึ่งพวกเขาไม่ได้ทำ ความจริงที่ว่า MS (ผมถือว่าเจตนา) เริ่มใช้ BOM UTF-8 มากกว่า UTF-16 แสดงให้เห็นว่าพวกเขาเลื่อนตำแหน่งทำลายsh, perl, g++และเครื่องมือฟรีและมีประสิทธิภาพอื่น ๆ อีกมากมาย ต้องการทำงานหรือไม่ เพียงซื้อรุ่น MS MS สร้างปัญหาเฉพาะแพลตฟอร์มเช่นเดียวกับความเสียหายของช่วง \ x80- \ x95
bballdave025

30

ระบุ UTF-8 พร้อม BOM ได้ดีกว่า ฉันได้มาถึงข้อสรุปนี้อย่างหนัก ฉันกำลังทำงานในโครงการที่ผลลัพธ์อย่างใดอย่างหนึ่งคือไฟล์ CSVรวมถึงอักขระ Unicode

หากไฟล์ CSV ถูกบันทึกโดยไม่มี BOM Excel จะคิดว่าเป็น ANSI และแสดงซึ่งพูดไม่ชัด เมื่อคุณเพิ่ม "EF BB BF" ที่ด้านหน้า (ตัวอย่างเช่นโดยบันทึกอีกครั้งโดยใช้ Notepad ด้วย UTF-8 หรือ Notepad ++ กับ UTF-8 พร้อม BOM) Excel จะเปิดได้ดี

แนะนำให้ใช้การเตรียมอักขระ BOM เป็นไฟล์ข้อความ Unicode โดย RFC 3629: "UTF-8 ซึ่งเป็นรูปแบบการแปลง ISO 10646", พฤศจิกายน 2546 ที่http://tools.ietf.org/html/rfc3629 (ข้อมูลล่าสุดนี้อยู่ที่: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )


6
ขอบคุณสำหรับเคล็ดลับที่ยอดเยี่ยมนี้ในกรณีที่ไฟล์หนึ่งกำลังสร้างไฟล์ UTF-8 สำหรับใช้งานโดย Excel ในสถานการณ์อื่น ๆ แม้ว่าฉันจะยังคงปฏิบัติตามคำตอบอื่น ๆ และข้าม BOM
barfuin

5
นอกจากนี้ยังมีประโยชน์หากคุณสร้างไฟล์ที่มีเฉพาะ ASCII และใหม่กว่าอาจเพิ่มไม่ใช่แบบ ASCII ฉันเพิ่งพบปัญหาเช่นซอฟต์แวร์ที่คาดว่าจะ utf8 สร้างไฟล์ที่มีข้อมูลบางอย่างสำหรับการแก้ไขผู้ใช้ หากไฟล์เริ่มต้นมีเฉพาะ ASCII จะถูกเปิดในตัวแก้ไขบางตัวและบันทึกไว้ไฟล์นั้นจะจบลงใน latin-1 และทุกอย่างจะหยุดพัก ถ้าฉันเพิ่ม BOM มันจะถูกตรวจพบในรูปแบบ UTF8 โดยเครื่องมือแก้ไขและทุกอย่างทำงานได้
Roberto Alsina

1
ฉันพบเครื่องมือที่เกี่ยวข้องกับการเขียนโปรแกรมหลายอย่างซึ่งต้องการ BOM เพื่อรับรู้ไฟล์ UTF-8 อย่างถูกต้อง Visual Studio, SSMS, SoureTree ....
kjbartel

5
คุณจะอ่านคำแนะนำสำหรับการใช้ BOM ใน RFC นั้นได้ที่ไหน อย่างมากที่สุดมีคำแนะนำที่ดีที่จะไม่ห้ามในบางสถานการณ์ที่การทำเช่นนั้นเป็นเรื่องยาก
Deduplicator

8
Excel คิดว่าเป็น ANSI และแสดงซึ่งพูดพล่อยๆแล้วปัญหาอยู่ใน Excel
ไอแซค

17

BOM มีแนวโน้มที่จะบูม (ไม่มีการเล่นสำนวนเจตนา (sic)) บางแห่ง และเมื่อมันบูม (ตัวอย่างเช่นไม่ได้รับการยอมรับจากเบราว์เซอร์บรรณาธิการ ฯลฯ ) มันจะปรากฏเป็นตัวอักษรแปลก ๆที่จุดเริ่มต้นของเอกสาร (เช่นไฟล์ HTML, การตอบสนองJSON , RSS , ฯลฯ ) และทำให้เกิดชนิดของ embarrassments เช่นนั้นปัญหาการเข้ารหัสที่ผ่านมามีประสบการณ์ในช่วงการพูดคุยของโอบามาบน Twitter

มันน่ารำคาญมากเมื่อมันปรากฏขึ้นในสถานที่ยากต่อการดีบักหรือเมื่อการทดสอบถูกละเลย ดังนั้นจึงเป็นการดีที่สุดที่จะหลีกเลี่ยงมันเว้นแต่คุณจะต้องใช้มัน


ใช่ใช้เวลาเพียงชั่วโมงในการระบุปัญหาที่เกิดจากไฟล์ที่ถูกเข้ารหัสเป็น UTF-8 แทนที่จะเป็น UTF-8 ที่ไม่มี BOM (ปัญหาปรากฏขึ้นเฉพาะใน IE7 เพื่อที่ทำให้ฉันในการไล่ล่าห่านค่อนข้างฉันใช้ Django ของ "รวม".)
user984003

ผู้อ่านในอนาคต: โปรดทราบว่าปัญหาทวีตที่ฉันได้กล่าวถึงข้างต้นไม่ได้เกี่ยวข้องกับ BOM อย่างเคร่งครัด แต่ถ้าเป็นเช่นนั้นทวีตจะถูกอ่านไม่ออกในลักษณะที่คล้ายกัน แต่เมื่อเริ่มทวีต
Halil Özgür

12
@ user984003 ไม่ปัญหาคือ Microsoft ทำให้คุณเข้าใจผิด สิ่งที่เรียกว่า UTF-8 ไม่ใช่ UTF-8 สิ่งที่เรียกว่า UTF-8 ที่ไม่มี BOM คือสิ่งที่เป็น UTF-8 จริงๆ
tchrist

"sic" เพิ่มอะไรใน "no pun pun" ของคุณ
JoelFan

2
@JoelFan ผมจำไม่ได้อีกต่อไป แต่ผมคิดว่าปุนอาจจะได้รับการตั้งใจแม้จะมีการเรียกร้องของผู้เขียน :)
Halil Özgür

17

คำถาม: UTF-8 กับ UTF-8 ต่างกันอย่างไรถ้าไม่มี BOM ไหนดีกว่ากัน

นี่คือข้อความที่ตัดตอนมาจากบทความ Wikipedia บนเครื่องหมายคำสั่งซื้อ (BOM)ที่ฉันเชื่อว่าให้คำตอบที่ดีสำหรับคำถามนี้

เกี่ยวกับความหมายของ BOM และ UTF-8:

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

อาร์กิวเมนต์ที่ ไม่ ใช้ BOM:

แรงจูงใจหลักสำหรับการไม่ใช้ BOM คือความเข้ากันได้ย้อนหลังกับซอฟต์แวร์ที่ไม่ได้รับการ Unicode ... แรงจูงใจอีกอย่างสำหรับการไม่ใช้ BOM คือการสนับสนุน UTF-8 ว่าเป็นการเข้ารหัส "ค่าเริ่มต้น"

อาร์กิวเมนต์ สำหรับการ ใช้ BOM:

อาร์กิวเมนต์สำหรับการใช้ BOM นั้นไม่จำเป็นต้องมีการวิเคราะห์แบบฮิวริสติกเพื่อกำหนดตัวอักษรที่เข้ารหัสไฟล์ การวิเคราะห์ในอดีตเพื่อแยกความแตกต่างการเข้ารหัส 8 บิตต่าง ๆ มีความซับซ้อนผิดพลาดง่ายและบางครั้งช้า มีไลบรารีจำนวนมากที่ช่วยให้งานง่ายขึ้นเช่น Mozilla Universal Charset Detector และ International Components for Unicode

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

โดยเฉพาะอย่างยิ่งคอมไพเลอร์และล่ามของ Microsoftและซอฟต์แวร์หลายชิ้นใน Microsoft Windows เช่น Notepad จะอ่านข้อความ UTF-8 ไม่ถูกต้องเว้นแต่จะมีเฉพาะอักขระ ASCII หรือเริ่มต้นด้วย BOM และจะเพิ่ม BOM เมื่อเริ่มต้นเมื่อบันทึก ข้อความเป็น UTF-8 Google เอกสารจะเพิ่ม BOM เมื่อมีการดาวน์โหลดเอกสาร Microsoft Word เป็นไฟล์ข้อความธรรมดา

สิ่งไหนดีกว่า มี หรือ ไม่มี BOM:

IETFแนะนำว่าหากโปรโตคอล (ก) มักจะใช้ UTF-8 หรือ (ข) มีบางส่วนทางอื่นที่จะระบุว่าการเข้ารหัสจะถูกนำมาใช้แล้วมัน“ควรห้ามการใช้ U + FEFF เป็นลายเซ็น.”

บทสรุปของฉัน:

ใช้ BOM ก็ต่อเมื่อความเข้ากันได้กับแอพพลิเคชั่นซอฟต์แวร์นั้นเป็นสิ่งจำเป็นอย่างยิ่ง

โปรดทราบว่าในขณะที่บทความ Wikipedia ที่อ้างถึงระบุว่าแอปพลิเคชันของ Microsoft จำนวนมากพึ่งพา BOM เพื่อตรวจจับ UTF-8 อย่างถูกต้อง แต่นี่ไม่ใช่กรณีสำหรับแอปพลิเคชัน Microsoft ทั้งหมด ยกตัวอย่างเช่นการชี้โดย@barlopเมื่อใช้งาน Windows Command Prompt กับ UTF-8 คำสั่งดังกล่าวtypeและmoreไม่ได้คาดหวัง BOM ที่จะนำเสนอ หากรายการวัสดุเป็นปัจจุบันก็อาจจะเป็นปัญหาที่มันเป็นสำหรับการใช้งานอื่น ๆ


chcpคำสั่งให้การสนับสนุน UTF-8 ( โดยไม่ต้อง BOM) ที่ผ่านหน้ารหัส65001


5
ฉันควรที่จะเข้มงวดเพื่อโดยไม่มีรายการวัสดุ ฉันพบว่า.htaccessและgzip compressionเมื่อใช้ร่วมกับ UTF-8 BOM ให้ข้อผิดพลาดในการเข้ารหัสเปลี่ยนเป็นการเข้ารหัสใน UTF-8 โดยไม่ต้อง BOM ทำตามคำแนะนำตามที่อธิบายไว้ที่นี่เพื่อแก้ปัญหา
Chetabahana

1
'แรงจูงใจสำหรับการไม่ใช้ BOM คือการสนับสนุนให้ UTF-8 เป็นการเข้ารหัส "ค่าเริ่มต้น" - ข้อโต้แย้งใดที่แข็งแกร่งและถูกต้องคุณสามารถหยุดคำตอบที่นั่นได้จริง! ... ; -o เว้นแต่คุณจะมีความคิดที่ดีกว่าสำหรับการแสดงข้อความสากลนั่นคือ ;) (ฉันไม่รู้ว่าคุณอายุเท่าไหร่คุณต้องทนทุกข์ทรมานมากแค่ไหนในยุคก่อนยูทาห์ UTF8 (เมื่อนักภาษาศาสตร์คิดอย่างยิ่งว่าจะเปลี่ยนตัวอักษร) แต่ฉันสามารถบอกคุณได้ว่าทุกวินาทีที่เราเข้าใกล้การขี่ม้า ความยุ่งเหยิงของการเข้ารหัสไบต์เดียวแบบโบราณที่ไม่มีเมตาดาต้าแทนการมี "ตัวตน" คือความสุขที่บริสุทธิ์)
Sz.

ดูความคิดเห็นนี้เกี่ยวกับวิธีการเพิ่ม BOM (หรืออะไรก็ได้!) ในรูปแบบไฟล์ข้อความที่ง่ายที่สุด "ข้อความธรรมดา" ซึ่งหมายถึงการป้องกันรูปแบบการเข้ารหัสข้อความสากลที่ดีที่สุดไม่ให้เป็น "ธรรมดา" และ "ง่าย" (เช่น "เหนือศีรษะ")! ...
Sz.

BOM เป็นปัญหาส่วนใหญ่บน Linux เนื่องจากยูทิลิตี้หลายตัวไม่สนับสนุน Unicode ที่จะเริ่มต้นด้วย (พวกมันจะถูกตัดอย่างมีความสุขในช่วงกลางของ codepoints เป็นต้น) สำหรับสภาพแวดล้อมซอฟต์แวร์ที่ทันสมัยอื่น ๆ ส่วนใหญ่ให้ใช้ BOM เมื่อการเข้ารหัสไม่โปร่งใส (ผ่านข้อมูลจำเพาะหรือข้อมูลเมตา)
Eric Grange

9

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

ดังที่ได้กล่าวมาการใช้ UTF BOM (Byte Order Mark) ใด ๆ ในการพิจารณาว่าสตริงนั้นเป็น UTF-8 หรือไม่นั้นจะได้รับการศึกษาการคาดเดา หากมีข้อมูลเมตาที่เหมาะสม (เช่นcharset="utf-8") แสดงว่าคุณรู้อยู่แล้วว่าคุณควรใช้อะไร แต่ไม่เช่นนั้นคุณจะต้องทดสอบและตั้งสมมติฐาน สิ่งนี้เกี่ยวข้องกับการตรวจสอบว่าไฟล์มาจากสตริงเริ่มต้นด้วยรหัสไบต์ฐานสิบหก EF BB BF หรือไม่

หากพบรหัสไบต์ที่สอดคล้องกับ UTF-8 BOM ความน่าจะเป็นสูงพอที่จะถือว่าเป็น UTF-8 และคุณสามารถไปจากที่นั่นได้ อย่างไรก็ตามเมื่อถูกบังคับให้ต้องเดาสิ่งนี้การตรวจสอบข้อผิดพลาดเพิ่มเติมในขณะที่อ่านยังคงเป็นความคิดที่ดีในกรณีที่มีบางอย่างที่อ่านไม่ออก คุณควรถือว่า BOM ไม่ใช่ UTF-8 (เช่น latin-1 หรือ ANSI) ถ้าอินพุตไม่ควรเป็น UTF-8 ตามแหล่งที่มา อย่างไรก็ตามถ้าไม่มี BOM คุณสามารถกำหนดได้ว่าควรจะเป็น UTF-8 หรือไม่โดยตรวจสอบการเข้ารหัส

ทำไมไม่แนะนำ BOM

  1. ซอฟต์แวร์ที่ไม่ได้ใช้ Unicode ที่ทราบหรือไม่ดีอาจถือว่าเป็น latin-1 หรือ ANSI และจะไม่ตัด BOM ออกจากสตริงซึ่งอาจทำให้เกิดปัญหาได้
  2. ไม่จำเป็นจริงๆ (เพียงตรวจสอบว่าเนื้อหานั้นสอดคล้องและใช้ UTF-8 เป็นทางเลือกเสมอเมื่อไม่พบการเข้ารหัสตาม)

เมื่อใดควรคุณเข้ารหัสกับ BOM หรือไม่?

หากคุณไม่สามารถบันทึกข้อมูลเมตาได้ด้วยวิธีอื่น (ผ่านแท็กชุดอักขระหรือเมตาดาต้าระบบไฟล์) และโปรแกรมที่ใช้เช่น BOM คุณควรเข้ารหัสด้วย BOM นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งใน Windows โดยทั่วไปแล้วสิ่งใดก็ตามที่ไม่มี BOM จะถือว่าใช้หน้ารหัสดั้งเดิม BOM บอกโปรแกรมเช่น Office ว่าใช่ข้อความในไฟล์นี้คือ Unicode นี่คือการเข้ารหัสที่ใช้

เมื่อพูดถึงมันไฟล์เดียวที่ฉันเคยมีปัญหาจริงๆคือไฟล์ CSV ขึ้นอยู่กับโปรแกรมว่าจะต้องมีหรือไม่มี BOM ตัวอย่างเช่นหากคุณใช้ Excel 2007+ บน Windows จะต้องเข้ารหัสด้วย BOM หากคุณต้องการเปิดอย่างราบรื่นและไม่ต้องหันไปใช้การนำเข้าข้อมูล


2
ส่วนสุดท้ายของคำตอบของคุณถูกต้อง 100% เหตุผลเดียวที่ใช้ BOM คือเมื่อคุณต้องทำงานร่วมกับซอฟต์แวร์ buggy ที่ไม่ได้ใช้ UTF-8 เป็นค่าเริ่มต้นในการแยกวิเคราะห์ไฟล์ที่ไม่รู้จัก
rmunn

8

ควรสังเกตว่าสำหรับไฟล์บางไฟล์คุณต้องไม่มี BOM แม้กระทั่งบน Windows ตัวอย่างSQL*plusหรือVBScriptไฟล์ ในกรณีที่ไฟล์ดังกล่าวมี BOM คุณจะได้รับข้อผิดพลาดเมื่อพยายามเรียกใช้งาน


8

UTF-8 พร้อม BOM จะช่วยได้ก็ต่อเมื่อไฟล์มีอักขระที่ไม่ใช่ ASCII บางตัวเท่านั้น ถ้ามันรวมอยู่ด้วยและไม่มีเลยก็จะทำให้แอปพลิเคชั่นรุ่นเก่าที่อาจตีความไฟล์เป็น ASCII ธรรมดา แอปพลิเคชันเหล่านี้จะล้มเหลวอย่างแน่นอนเมื่อพวกเขาเจออักขระที่ไม่ใช่ ASCII ดังนั้นในความเห็นของฉัน BOM ควรถูกเพิ่มเมื่อไฟล์สามารถทำได้เท่านั้นและไม่ควรตีความว่าเป็น ASCII ธรรมดาอีกต่อไป

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

อย่าทำสิ่งใดคาดหวัง BOM สำหรับ UTF-8


7

อ้างถึงที่ด้านล่างของหน้า Wikipedia บน BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

"ไม่จำเป็นต้องใช้ BOM หรือแนะนำสำหรับ UTF-8 แต่อาจพบในบริบทที่ข้อมูล UTF-8 ถูกแปลงจากรูปแบบการเข้ารหัสอื่น ๆ ที่ใช้ BOM หรือที่ BOM ใช้เป็นลายเซ็น UTF-8"


2
คุณมีตัวอย่างใดบ้างที่ซอฟต์แวร์ตัดสินว่าจะใช้ UTF-8 ที่มี / ไม่มี BOM หรือไม่โดยพิจารณาจากการเข้ารหัสก่อนหน้านี้ที่เข้ารหัสมามี BOM หรือไม่! ดูเหมือนว่าจะเป็นข้ออ้างที่ไร้สาระ
barlop

7

UTF-8 ที่ไม่มี BOM ไม่มี BOM ซึ่งไม่ได้ทำให้ดีไปกว่า UTF-8 ที่มี BOM ยกเว้นเมื่อผู้ใช้ไฟล์ต้องการทราบ (หรือจะได้ประโยชน์จากการรู้) ว่าไฟล์นั้นเข้ารหัส UTF-8 หรือไม่ หรือไม่.

BOM มักจะมีประโยชน์ในการกำหนด endianness ของการเข้ารหัสซึ่งไม่จำเป็นสำหรับกรณีการใช้งานส่วนใหญ่

นอกจากนี้ BOM อาจเป็นเสียง / ความเจ็บปวดที่ไม่จำเป็นสำหรับผู้บริโภคที่ไม่ทราบหรือไม่สนใจและอาจส่งผลให้เกิดความสับสนของผู้ใช้


2
"ซึ่งไม่มีประโยชน์สำหรับ UTF-8 เพราะมันคือ 8-bits ต่อ glyph อยู่แล้ว" เอ่อ ... ไม่ร่ายมนตร์ ASCII-7 เพียง 8 บิตใน UTF-8 อะไรที่มากกว่านั้นจะเป็น 16, 24, หรือ 32 บิต
Powerlord

3
"BOM มักจะมีประโยชน์ในการกำหนด endianness ของการเข้ารหัสซึ่งไม่จำเป็นสำหรับกรณีการใช้งานส่วนใหญ่" ... endianness ใช้ไม่ได้กับ UTF-8 โดยไม่คำนึงถึงกรณีการใช้งาน
JoelFan

6

ฉันมองสิ่งนี้จากมุมมองที่ต่างออกไป ฉันคิดว่าUTF-8 พร้อม BOM จะดีกว่าเพราะให้ข้อมูลเพิ่มเติมเกี่ยวกับไฟล์ ฉันใช้ UTF-8 ที่ไม่มี BOM ก็ต่อเมื่อฉันประสบปัญหา

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

โปรดทราบว่า Windows คลาสสิก ' Notepadจะบันทึกไฟล์ด้วย BOM โดยอัตโนมัติเมื่อคุณพยายามบันทึกไฟล์ที่สร้างขึ้นใหม่ด้วยการเข้ารหัส UTF-8

ฉันเป็นการส่วนตัวบันทึกไฟล์สคริปต์ฝั่งเซิร์ฟเวอร์(.asp, .ini, .aspx) ด้วย BOMและไฟล์ .html โดยไม่ต้อง BOM


4
ขอบคุณสำหรับเคล็ดลับที่ยอดเยี่ยมเกี่ยวกับ windows classic Notepad ฉันใช้เวลาไปกับการค้นหาสิ่งเดียวกัน ผลที่ตามมาของฉันคือการใช้ Notepad ++ แทน windows classic Notepad ทุกครั้ง :-)
barfuin

คุณควรใช้ madedit ดีกว่า มันเป็น Editor เพียงตัวเดียวที่อยู่ในโหมด hex - แสดงหนึ่งตัวอักษรถ้าคุณเลือกลำดับ utf-8 byte แทน 1: 1 Basis ระหว่าง byte และ character hex-Editor ที่รับรู้เกี่ยวกับไฟล์ UTF-8 ควรมีลักษณะเหมือน madedit
bright

@brighty ฉันไม่คิดว่าคุณต้องการแบบหนึ่งต่อหนึ่งเพื่อประโยชน์ของ BOM ไม่เป็นไรมันไม่ได้ใช้อะไรมากนักที่จะรู้ว่า utf-8 BOM คือ efbbbf หรือ fffe (ของ fffe ถ้าอ่านผิด) หนึ่งสามารถลบไบต์เหล่านั้นได้ ไม่เลวเลยที่จะมีการแมปสำหรับไฟล์ส่วนที่เหลือ แต่สามารถลบไบต์ด้วยไบต์ด้วย
barlop

@barlop ทำไมคุณต้องการลบ utf-8 BOM ถ้าเนื้อหาของไฟล์นั้นถูกเข้ารหัส utf-8 BOM ได้รับการยอมรับจากผู้ดูข้อความที่ทันสมัยการควบคุมข้อความรวมถึงเครื่องมือแก้ไขข้อความ มุมมองแบบหนึ่งต่อหนึ่งของลำดับ utf-8 ไม่สมเหตุสมผลเนื่องจาก n ไบต์ส่งผลให้มีอักขระหนึ่งตัว แน่นอน text-editor หรือ hex-editor ควรอนุญาตให้ลบไบต์ใด ๆ แต่สิ่งนี้สามารถนำไปสู่ลำดับ utf-8 ที่ไม่ถูกต้อง
bright

@brighty utf-8 พร้อม bom เป็นการเข้ารหัสและ utf-8 ที่ไม่มี bom เป็นการเข้ารหัส cmd prompt ใช้ utf8 โดยไม่มี bom .. ดังนั้นหากคุณมีไฟล์ utf8 คุณจะรันคำสั่งchcp 65001สำหรับการสนับสนุน utf8 ก็คือ utf8 โดยไม่มี bom ถ้าคุณทำtype myfileมันจะแสดงอย่างถูกต้องหากไม่มีระเบิด หากคุณทำecho aaa>a.aหรือecho אאא>a.a ส่งออกตัวอักษรไปยังไฟล์ aa และคุณมี chcp 65001 มันจะส่งออกโดยไม่มี BOM
barlop

6

เมื่อคุณต้องการแสดงข้อมูลที่เข้ารหัสใน UTF-8 คุณอาจไม่ประสบปัญหา ประกาศตัวอย่างเช่นเอกสาร HTML เป็น UTF-8 และคุณจะมีทุกสิ่งที่แสดงในเบราว์เซอร์ของคุณที่อยู่ในเนื้อหาของเอกสาร

แต่นี่ไม่ใช่กรณีเมื่อเรามีข้อความเป็นCSVและ XML ทั้งบน Windows หรือ Linux

ตัวอย่างเช่นไฟล์ข้อความใน Windows หรือ Linux ซึ่งเป็นหนึ่งในสิ่งที่ง่ายที่สุดเท่าที่จะจินตนาการได้มันไม่ใช่ UTF-8 (ปกติ)

บันทึกเป็น XML และประกาศเป็น UTF-8:

<?xml version="1.0" encoding="UTF-8"?>

มันจะไม่แสดง (มันจะไม่สามารถอ่านได้) อย่างถูกต้องแม้ว่ามันจะประกาศเป็น UTF-8

ฉันมีชุดของข้อมูลที่ประกอบด้วยตัวอักษรภาษาฝรั่งเศสซึ่งจำเป็นต้องได้รับการบันทึกเป็น XML สำหรับการเผยแพร่ โดยไม่ต้องสร้างไฟล์ UTF-8 จากจุดเริ่มต้น (เปลี่ยนตัวเลือกใน IDE และ "สร้างไฟล์ใหม่") หรือเพิ่ม BOM ที่จุดเริ่มต้นของไฟล์

$file="\xEF\xBB\xBF".$string;

ฉันไม่สามารถบันทึกตัวอักษรภาษาฝรั่งเศสในไฟล์ XML ได้


1
FTM ใน XML ฉันคิดว่าคุณควรเก็บไฟล์เป็น ASCII และใช้เอนทิตีแทน
Alois Mahdal

4
ฉันรู้ว่านี่เป็นคำตอบเก่า แต่ฉันแค่อยากจะพูดว่ามันผิด ไฟล์ข้อความบน Linux (ไม่สามารถพูดกับ Unixes อื่น ๆ ได้) โดยปกติ / เป็น / UTF-8
Functino

6

ข้อแตกต่างที่เป็นประโยชน์อย่างหนึ่งคือถ้าคุณเขียนเชลล์สคริปต์สำหรับ Mac OS X และบันทึกเป็น UTF-8 ธรรมดาคุณจะได้รับการตอบกลับ:

#!/bin/bash: No such file or directory

เพื่อตอบสนองต่อสาย shebang ที่ระบุว่าคุณต้องการใช้เชลล์ใด:

#!/bin/bash

หากคุณบันทึกเป็น UTF-8 ไม่มี BOM (พูดเป็นBBEdit ) ทั้งหมดจะดี


8
นั่นเป็นเพราะ Microsoft ได้เปลี่ยนความหมายของสิ่งที่มาตรฐานพูด UTF-8 ไม่มี BOM: พวกเขาได้สร้างMicrosoft UTF-8ซึ่งแทรก BOM ปลอมในหน้าสตรีมข้อมูลแล้วบอกคุณว่าไม่นี่คือ UTF-8 จริง มันไม่ใช่. มันเป็นเพียงการขยายและทำให้เสียหาย
tchrist

4

ตามที่กล่าวไว้ข้างต้น UTF-8 ที่มี BOM อาจทำให้เกิดปัญหากับซอฟต์แวร์ที่ไม่ได้รับการยอมรับ BOM (หรือที่เข้ากันได้) ฉันเคยแก้ไขไฟล์ HTML ที่เข้ารหัสเป็น UTF-8 + BOM ด้วย Mozilla-based KompoZerเนื่องจากไคลเอนต์ต้องการโปรแกรมWYSIWYG

เลย์เอาต์จะถูกทำลายอย่างถาวรเมื่อบันทึก ฉันใช้เวลาสักระยะเพื่อทำความคุ้นเคยกับสิ่งนี้ ไฟล์เหล่านี้ทำงานได้ดีใน Firefox แต่พบว่ามีการเล่นโวหาร CSS ใน Internet Explorer ที่ทำลายเลย์เอาต์อีกครั้ง หลังจากเล่นซอกับไฟล์ CSS ที่ลิงก์นานหลายชั่วโมงแล้วก็ไม่มีประโยชน์ฉันค้นพบว่า Internet Explorer ไม่ชอบไฟล์ HTML BOMfed ไม่มีอีกครั้ง.

นอกจากนี้ฉันเพิ่งพบสิ่งนี้ใน Wikipedia:

อักขระ shebang จะแสดงด้วยสองไบต์เดียวกันในการเข้ารหัส ASCII แบบขยายรวมถึง UTF-8 ซึ่งโดยทั่วไปจะใช้สำหรับสคริปต์และไฟล์ข้อความอื่น ๆ ในระบบที่คล้าย Unix ในปัจจุบัน อย่างไรก็ตามไฟล์ UTF-8 อาจเริ่มต้นด้วยเครื่องหมายสั่งทางเลือก (BOM); หากฟังก์ชั่น "exec" ตรวจพบไบต์ 0x23 0x21 โดยเฉพาะการแสดงตนของ BOM (0xEF 0xBB 0xBF) ก่อนที่ shebang จะป้องกันไม่ให้ล่ามสคริปต์ทำงาน ผู้มีอำนาจบางคนแนะนำให้ต่อต้านการใช้เครื่องหมายคำสั่งไบต์ในสคริปต์ POSIX (เหมือน Unix), [15] ด้วยเหตุผลนี้และสำหรับการทำงานร่วมกันที่กว้างขึ้นและข้อกังวลทางปรัชญา


4

คำถามที่พบบ่อยเกี่ยวกับ Unicode Byte Order Mark (BOM)ให้คำตอบโดยย่อ:

ถาม: ฉันควรจัดการกับ BOM อย่างไร

ตอบ: ต่อไปนี้เป็นแนวทางปฏิบัติบางประการ:

  1. โปรโตคอลเฉพาะ (เช่นข้อตกลงของ Microsoft สำหรับไฟล์. txt) อาจต้องใช้ BOM ในสตรีมข้อมูล Unicode บางไฟล์เช่นไฟล์ เมื่อคุณจำเป็นต้องปฏิบัติตามโปรโตคอลดังกล่าวให้ใช้ BOM

  2. โปรโตคอลบางตัวอนุญาต BOM ที่เป็นตัวเลือกในกรณีของข้อความที่ไม่ได้ติดแท็ก ในกรณีเหล่านั้น

    • ในกรณีที่ทราบว่าสตรีมข้อมูลข้อความเป็นข้อความธรรมดา แต่จากการเข้ารหัสที่ไม่รู้จัก BOM สามารถใช้เป็นลายเซ็นได้ หากไม่มี BOM การเข้ารหัสอาจเป็นอะไรก็ได้

    • ตำแหน่งที่สตรีมข้อมูลข้อความเป็นที่รู้จักกันว่าเป็นข้อความ Unicode ธรรมดา (แต่ไม่ใช่ endian ใด ๆ ) ดังนั้น BOM จึงสามารถใช้เป็นลายเซ็นได้ หากไม่มี BOM ข้อความควรถูกตีความเป็น big-endian

  3. โปรโตคอลแบบไบต์บางตัวคาดหวังอักขระ ASCII ที่จุดเริ่มต้นของไฟล์ หากใช้ UTF-8 กับโปรโตคอลเหล่านี้ควรหลีกเลี่ยงการใช้ BOM เนื่องจากการเข้ารหัสลายเซ็นฟอร์ม

  4. ในกรณีที่ทราบชนิดของสตรีมข้อมูลที่แม่นยำ (เช่น Unicode big-endian หรือ Unicode little-endian) ไม่ควรใช้ BOM โดยเฉพาะอย่างยิ่งทุกครั้งที่มีการประกาศสตรีมข้อมูลเป็น UTF-16BE, UTF-16LE, UTF-32BE หรือ UTF-32LE BOM จะต้องไม่ใช้ BOM


1

จากhttp://en.wikipedia.org/wiki/Byte-order_mark :

เครื่องหมายคำสั่งไบต์ (BOM) เป็นอักขระ Unicode ที่ใช้เพื่อส่งสัญญาณ endianness (ลำดับไบต์) ของไฟล์ข้อความหรือสตรีม จุดรหัสคือ U + FEFF การใช้ BOM เป็นทางเลือกและหากใช้ควรปรากฏที่จุดเริ่มต้นของสตรีมข้อความ นอกเหนือจากการใช้งานที่เฉพาะเจาะจงเป็นตัวบ่งชี้ลำดับไบต์อักขระ BOM อาจระบุว่ามีการเข้ารหัส Unicode หลายข้อความที่เข้ารหัส

การใช้ BOM ในไฟล์ของคุณเสมอจะทำให้แน่ใจได้ว่ามันเปิดอย่างถูกต้องในตัวแก้ไขที่รองรับ UTF-8 และ BOM

ปัญหาที่แท้จริงของฉันกับการขาด BOM มีดังต่อไปนี้ สมมติว่าเรามีไฟล์ซึ่งประกอบด้วย:

abc

หากไม่มี BOM จะเป็นการเปิดเป็น ANSI ในโปรแกรมแก้ไขส่วนใหญ่ ดังนั้นผู้ใช้รายอื่นของไฟล์นี้จึงเปิดไฟล์และผนวกอักขระดั้งเดิมบางตัวเช่น

abg-αβγ

อุ๊ปส์ ... ตอนนี้ไฟล์ยังอยู่ใน ANSI และคาดเดาว่า "αβγ" ไม่มีขนาด 6 ไบต์ แต่ 3 นี่ไม่ใช่ UTF-8 และทำให้เกิดปัญหาอื่น ๆ ในภายหลังในสายการพัฒนา


9
ตรวจสอบให้แน่ใจว่าไบต์ปลอม ๆ ปรากฏขึ้นในตอนต้นของซอฟต์แวร์ที่ไม่ทราบ BOM เย้.
Romain

1
@Romain Muller: เช่น PHP 5 จะโยนข้อผิดพลาด "เป็นไปไม่ได้" เมื่อคุณพยายามส่งส่วนหัวหลังจาก BOM
Piskvor ออกจากอาคาร

5
αβγไม่ใช่ ascii แต่สามารถปรากฏในการเข้ารหัส 8bit-ascii-bassed การใช้ BOM จะปิดการใช้งานผลประโยชน์ของ utf-8, ความเข้ากันได้กับ ascii (ความสามารถในการทำงานกับแอปพลิเคชัน lagacy ที่ใช้ ascii บริสุทธิ์)
ctrl-alt-delor

1
นี่คือคำตอบที่ผิด สตริงที่มี BOM อยู่ข้างหน้านั้นเป็นอย่างอื่นทั้งหมด มันไม่ควรที่จะอยู่ที่นั่น
tchrist

หากไม่มี BOM จะเป็นการเปิดเป็น ANSI ในโปรแกรมแก้ไขส่วนใหญ่ ฉันเห็นด้วยอย่างแน่นอน หากสิ่งนี้เกิดขึ้นคุณโชคดีถ้าคุณจัดการกับ Codepage ที่ถูกต้อง แต่แน่นอนว่ามันเป็นเพียงการเดาเพราะ Codepage ไม่ได้เป็นส่วนหนึ่งของไฟล์ BOM คือ
bright

1

นี่คือประสบการณ์ของฉันกับ Visual Studio, Sourcetreeและคำขอดึงซึ่งทำให้ฉันมีปัญหาบางอย่าง:

ดังนั้นจึงกลายเป็น BOM ที่มีลายเซ็นต์จะมีตัวอักษรจุดสีแดงในแต่ละไฟล์เมื่อตรวจสอบคำขอดึง (มันอาจจะค่อนข้างน่ารำคาญ)

ป้อนคำอธิบายภาพที่นี่

หากคุณวางไว้บนมันก็จะแสดงตัวละครเช่น "ufeff" แต่ปรากฎว่า Sourcetree ไม่แสดง bytemarks ประเภทเหล่านี้ดังนั้นมันจะจบลงด้วยการดึงคำขอของคุณซึ่งน่าจะเป็นเพราะ Visual Studio 2017 เข้ารหัสไฟล์ใหม่ตอนนี้ดังนั้นบางที Bitbucket ควรเพิกเฉยต่อสิ่งนี้หรือทำให้มันแสดงในอีกทางหนึ่งข้อมูลเพิ่มเติมที่นี่:

เครื่องหมายจุดสีแดง BitBucket diff


-4

UTF ที่มี BOM จะดีกว่าถ้าคุณใช้ UTF-8 ในไฟล์ HTML และถ้าคุณใช้ Serbian Cyrillic, Serbian Latin, German, Hungarian หรือภาษาแปลก ๆ ในหน้าเดียวกัน

นั่นคือความคิดเห็นของฉัน (30 ปีของการใช้คอมพิวเตอร์และอุตสาหกรรมไอที)


1
ฉันพบว่าสิ่งนี้เป็นจริงเช่นกัน หากคุณใช้อักขระนอกชุด 255 ASCII แรกและคุณไม่ต้องป้อน BOM เบราว์เซอร์จะตีความว่าเป็น ISO-8859-1 และคุณจะได้รับอักขระที่อ่านไม่ออก จากคำตอบข้างบนนี้เห็นได้ชัดว่าผู้ขายเบราว์เซอร์ทำสิ่งผิดเมื่อตรวจไม่พบ BOM แต่ถ้าคุณทำงานที่ Microsoft Edge / Mozilla / Webkit / Blink คุณไม่มีทางเลือก แต่ทำงานกับข้อบกพร่องที่แอพเหล่านี้มี
asontu

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