पिछले सप्ताह के लेख में, आपने एक छोटी प्रक्रिया सीखी जो अधिकांश एन्कोडिंग समस्याओं को हल करती है। लेकिन एक एन्कोडिंग समस्या है जिसे हल करना बहुत कठिन है।
मुझे पता है आपने इसे देखा है। (या शायद आप’ने इसे देखा है?) यह तब होता है जब एक घुंघराला उद्धरण ’ में बदल जाता है, या एक एम-डैश — में बदल जाता है। यह आपको पागल कर देगा। यह बस काम करना चाहिए!
आप एक विशाल तालिका बना सकते हैं, ताकि आप खराब वर्णों को ढूंढ सकें और उन्हें अच्छे से बदल सकें:
[{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 के रूप में सहेजेंगे। 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 स्ट्रिंग है, (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 के मुफ्त नमूना अध्याय में, आप ऐसा करने के लिए सर्वोत्तम तकनीकों और प्रक्रियाओं को सीखेंगे।