গত সপ্তাহের আর্টিকেলে, আপনি একটি সংক্ষিপ্ত প্রক্রিয়া শিখেছেন যা অধিকাংশ এনকোডিং সমস্যা সমাধান করে। लेकिन एक एनकोडिंग समस्या है जिसे हल करना बहुत कठिन है।
मैं जानता हूँ आपने इसे देखा है। (या शायद आपने इसे देखा है?) यह तब होता है जब एक कर्ली कोट (curly quote) ’ में बदल जाता है, या एक एम-डैश (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 बाइट्स का उपयोग करता है। और हमारी गड़बड़ स्ट्रिंग, they’re, में तीन कैरेक्टर हैं जहां केवल एक होना चाहिए। यह संयोग से अधिक लगता है, है ना?
लगता है उन तीन बाइट्स को 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 के रूप में सेव करेंगे। रूबी मददगार ढंग से इसे आपके लिए 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 स्ट्रिंग है, (they’re)
- जो एक Windows-1252 स्ट्रिंग से परिवर्तित हुई है, (they’re)
- जिनके बाइट्स पढ़े जाने चाहिए थे UTF-8 के रूप में (they’re)
इसे ठीक करने के लिए, आपको बस उन पिछड़े चरणों का पालन करना होगा। UTF-8 स्ट्रिंग को वापस Windows-1252 स्ट्रिंग में बदलने के लिए encode का उपयोग करें। फिर, उस गलत-एनकोडेड Windows-1252 स्ट्रिंग को UTF-8 के रूप में पढ़ने के लिए बाध्य करने के लिए force_encoding का उपयोग करें:
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 के मुफ्त नमूना अध्याय में, आप ऐसा करने के लिए सर्वोत्तम तकनीकें और प्रक्रियाएं सीखेंगे।