Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

วิธีการรับจากพวกเขาถึงพวกเขา

ในบทความของสัปดาห์ที่แล้ว คุณได้เรียนรู้กระบวนการสั้นๆ ที่แก้ปัญหาการเข้ารหัสส่วนใหญ่ แต่มีปัญหาการเข้ารหัสปัญหาหนึ่งที่แก้ไขได้ยากกว่ามาก

ฉันรู้ว่าคุณเคยเห็นมัน (หรือบางทีคุณเคยเห็นมันแล้ว?) เมื่อคำพูดหยิกกลายเป็น â €™ หรือ em-dash กลายเป็น — มันจะทำให้คุณคิดว่าคุณบ้าไปแล้ว มันน่าจะใช้ได้นะ!

คุณสามารถสร้างโต๊ะขนาดยักษ์ได้ ดังนั้นคุณจึงสามารถค้นหาตัวละครที่ไม่ดีและแทนที่ด้วยตารางที่ดีได้:

[{broken: '–',    fixed: "—"}
 {broken: "—",    fixed: "–"}
 {broken: "‘",    fixed: "‘"}
 {broken: "’",    fixed: "’"}
 {broken: "“",    fixed: "“"}
 {broken: "”", fixed: "”"}, ...]

แต่มีวิธีแก้ไขอักขระที่ใช้งานไม่ได้และง่ายกว่าและน่าเชื่อถือกว่า

ทำไมการพิมพ์ที่ดีถึงพังเสมอ

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

irb(main):001:0> "they’re".bytes
=> [116, 104, 101, 121, 226, 128, 153, 114, 101]

แม้ว่าสตริงจะมีอักขระเพียง 7 ตัว แต่ก็มีอักขระแทน 9 ไบต์!

เมื่อคุณมุ่งเน้นที่คำพูดหยิก:

irb(main):002:0> "’".bytes
=> [226, 128, 153]

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

ดูเหมือนว่าสามไบต์นั้นควรอ่านเป็น UTF-8 โดยจะแทนค่าอ้างอิงแบบโค้ง แทน แต่ละไบต์ กำลังแสดงเป็นตัวละครอื่น ดังนั้นการเข้ารหัสใดที่จะแสดง [226, 128, 153] เป็น ’ ? หากคุณดูตารางการเข้ารหัสยอดนิยมสองสามตาราง คุณจะเห็นว่าเป็น Windows-1252

ตรวจสอบได้ใน irb :

irb(main):003:0> "they’re".force_encoding("Windows-1252").encode("UTF-8")
=> "they’re"

(เราต้องการ .encode("UTF-8") อันสุดท้าย เพื่อแสดงสตริงในคอนโซล)

ใช่! นั่นคือปัญหา แต่มันแย่ลงไปอีก

ข้อมูลควรจะเป็น UTF-8 แต่กำลังอ่านผิดเป็น Windows-1252 แต่คุณอาจจะบันทึกข้อมูลนั้นลงในฐานข้อมูลหรือไฟล์เป็น UTF-8 Ruby จะช่วยแปลงเป็น UTF-8 ให้คุณอย่างเป็นประโยชน์ ดังนั้นคุณจะได้:

irb(main):004:0> "they’re".force_encoding("Windows-1252").encode("UTF-8")
=> "they’re"
irb(main):005:0> "they’re".force_encoding("Windows-1252").encode("UTF-8").bytes
=> [116, 104, 101, 121, 195, 162, 226, 130, 172, 226, 132, 162, 114, 101]

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

แก้ไขอย่างไร

ทำอย่างไรให้สิ่งต่างๆ กลับมาเป็นปกติ? ลองคิดถึงปัญหาย้อนหลังกัน:

  • คุณมีสตริง UTF-8 (เป็น)

  • แปลงจากสตริง Windows-1252 (เป็น)

  • ซึ่งไบต์ ควรจะเป็น อ่านว่า UTF-8 (คือ)

ในการแก้ไข คุณต้องทำตามขั้นตอนย้อนกลับ ใช้ encode เพื่อแปลงสตริง UTF-8 กลับเป็นสตริง Windows-1252 จากนั้นใช้ force_encoding เพื่อบังคับให้สตริง Windows-1252 ที่เข้ารหัสผิดนั้นถูกอ่านเป็น UTF-8:

irb(main):006:0> "they’re".encode("Windows-1252").force_encoding("UTF-8")
=> "they’re"

แก้ไขแล้ว!

มีปัญหาเล็กน้อย…

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

หากเป็นกรณีนี้ คุณไม่สามารถเรียกใช้โค้ดนั้นอย่างสุ่มสี่สุ่มห้าในทุกสตริง:

irb(main):007:0> "they’re".encode("Windows-1252").force_encoding("UTF-8")
=> "they’re"
irb(main):008:0> "they’re".encode("Windows-1252").force_encoding("UTF-8")
=> "they\x92re"

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

คุณสามารถใช้ฮิวริสติกได้:เปลี่ยนเฉพาะสตริงที่มีหนึ่งในอักขระที่ไม่ถูกต้อง เช่น â . วิธีนี้ใช้ได้ผลดีหากอักขระเช่น â จะไม่ปรากฏในสตริงที่ถูกต้อง

ครั้งล่าสุดที่ฉันแก้ไขข้อผิดพลาดประเภทนี้ ฉันต้องการเล่นอย่างปลอดภัย ฉันใช้เครื่องมือที่มีประโยชน์อีกอย่างหนึ่งเพื่อช่วย:ดวงตาของฉัน

เมื่อใดก็ตามที่ฉันพบสตริงที่เข้ารหัสไม่ดี ฉันจะพิมพ์ออกมาพร้อมกับแทนที่:

Changing title with ID 6 from "They’re over there!" to "They’re over there!"

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

ฉันคิดว่าปวดหัว

อย่างที่ฉันพูดไปเมื่อสัปดาห์ที่แล้ว การตีความข้อมูลเดียวกันในหัวของคุณแบบต่างๆ กันเป็นเรื่องยาก! แต่ถ้าคุณสับสนให้สำรวจใน irb คอนโซลจะช่วย ลองเลย! เปิดขึ้นมาแล้วดูว่าคุณสามารถกลับไปกลับมาระหว่าง . ได้ไหม และ — , หรือ และ “ .

การฝึกฝนแนวคิดที่ซับซ้อนเช่นนี้เป็นวิธีที่เร็วที่สุดในการรู้สึกมั่นใจเมื่อคุณต้องการ และในบทตัวอย่างฟรีของ Practicing Rails คุณจะได้เรียนรู้เทคนิคและกระบวนการที่ดีที่สุดในการทำสิ่งนั้น