আপনি শুধুমাত্র একটি স্ট্রিং এর এনকোডিং সম্পর্কে চিন্তা করেন যখন এটি ভেঙে যায়৷৷ যখন আপনি আপনার ব্যতিক্রম ট্র্যাকার চেক করুন এবং দেখুন
Encoding::InvalidByteSequenceError: "\xFE" on UTF-8
তোমার মুখের দিকে তাকিয়ে অথবা হয়ত "তারা" "তারা" হিসাবে দেখাতে শুরু করে৷
৷সুতরাং, যখন আপনার একটি খারাপ এনকোডিং থাকে, তখন আপনি কীভাবে বুঝতে পারবেন কী ভেঙে গেছে? এবং কিভাবে আপনি এটি ঠিক করতে পারেন?
এনকোডিং কি?
যদি আপনি কল্পনা করতে পারেন যে এনকোডিং একটি স্ট্রিংকে কী করে, এই বাগগুলি ঠিক করা সহজ৷
আপনি একটি স্ট্রিংকে বাইটের অ্যারে বা ছোট সংখ্যা হিসাবে ভাবতে পারেন:
irb(main):001:0> "hello!".bytes
=> [104, 101, 108, 108, 111, 33]
এই এনকোডিং-এ, 104
মানে h
, 33
মানে !
, এবং তাই।
আপনি যখন ইংরেজিতে কম সাধারণ অক্ষর ব্যবহার করেন তখন এটি আরও জটিল হয়ে ওঠে:
irb(main):002:0> "hellṏ!".bytes
=> [104, 101, 108, 108, 225, 185, 143, 33]
এখন কোন সংখ্যাটি কোন অক্ষরকে প্রতিনিধিত্ব করে তা বলা কঠিন। এক বাইটের পরিবর্তে, ṏ
বাইটের গ্রুপ [225, 185, 143]
দ্বারা প্রতিনিধিত্ব করা হয় . কিন্তু এখনও বাইট এবং অক্ষরের মধ্যে একটি সম্পর্ক আছে। এবং একটি স্ট্রিং এর এনকোডিং সেই সম্পর্ককে সংজ্ঞায়িত করে৷৷
আপনি যখন বিভিন্ন এনকোডিং চেষ্টা করেন তখন বাইটের একক সেট কেমন দেখায় তা একবার দেখুন:
# Try an ISO-8859-1 string with a special character!
irb(main):003:0> str = "hellÔ!".encode("ISO-8859-1"); str.encode("UTF-8")
=> "hellÔ!"
irb(main):004:0> str.bytes
=> [104, 101, 108, 108, 212, 33]
# What would that string look like interpreted as ISO-8859-5 instead?
irb(main):005:0> str.force_encoding("ISO-8859-5"); str.encode("UTF-8")
=> "hellд!"
irb(main):006:0> str.bytes
=> [104, 101, 108, 108, 212, 33]
বাইট পরিবর্তন হয়নি। কিন্তু সেটা মোটেও ঠিক মনে হচ্ছে না। এনকোডিং পরিবর্তন করলে বাইট পরিবর্তন না করে স্ট্রিং প্রিন্ট করার পদ্ধতি পরিবর্তন হয়।
এবং সমস্ত স্ট্রিং সমস্ত এনকোডিংয়ে উপস্থাপন করা যায় না৷ :
irb(main):006:0> "hi∑".encode("Windows-1252")
Encoding::UndefinedConversionError: U+2211 to WINDOWS-1252 in conversion from UTF-8 to WINDOWS-1252
from (irb):61:in `encode'
from (irb):61
from /usr/local/bin/irb:11:in `<main>'
বেশিরভাগ এনকোডিং ছোট, এবং প্রতিটি সম্ভাব্য অক্ষর পরিচালনা করতে পারে না। আপনি সেই ত্রুটিটি দেখতে পাবেন যখন একটি এনকোডিংয়ে একটি অক্ষর অন্যটিতে বিদ্যমান থাকে না বা যখন রুবি বুঝতে পারে না যে দুটি এনকোডিংয়ের মধ্যে একটি অক্ষর কীভাবে অনুবাদ করা যায়।
আপনি যদি encode
-এ অতিরিক্ত বিকল্পগুলি পাস করেন তবে আপনি এই ত্রুটিটি সমাধান করতে পারেন৷ :
irb(main):064:0> "hi∑".encode("Windows-1252", invalid: :replace, undef: :replace)
=> "hi?"
invalid
এবং undef
বিকল্পগুলি এমন অক্ষরগুলিকে প্রতিস্থাপন করে যা অন্য অক্ষর দিয়ে অনুবাদ করা যায় না। ডিফল্টরূপে, সেই প্রতিস্থাপন অক্ষর হল ?
. (যখন আপনি ইউনিকোডে রূপান্তর করেন, এটি �)।
দুর্ভাগ্যবশত, যখন আপনি অক্ষরগুলিকে encode
দিয়ে প্রতিস্থাপন করেন , আপনি তথ্য হারাতে পারেন। আপনার কোন ধারণা নেই কোন বাইটগুলি ?
দ্বারা প্রতিস্থাপিত হয়েছে . কিন্তু আপনার যদি সেই নতুন এনকোডিং-এ আপনার ডেটার প্রয়োজন হয়, তাহলে ডেটা হারানো জিনিসগুলি ভাঙার চেয়ে ভাল হতে পারে৷
এ পর্যন্ত, আপনি এনকোডিং বুঝতে সাহায্য করার জন্য তিনটি মূল স্ট্রিং পদ্ধতি দেখেছেন:
-
encode
, যা একটি স্ট্রিংকে অন্য এনকোডিং-এ অনুবাদ করে (নতুন এনকোডিং-এ অক্ষরকে তাদের সমতুল্য রূপান্তর করা) -
bytes
, যা আপনাকে বাইটগুলি দেখাবে যা একটি স্ট্রিং তৈরি করে -
force_encoding
, যা আপনাকে দেখাবে সেই বাইটগুলিকে ভিন্ন এনকোডিং দ্বারা ব্যাখ্যা করা হলে কেমন দেখাবে
encode
এর মধ্যে প্রধান পার্থক্য এবং force_encoding
এটা হল encode
bytes
পরিবর্তন হতে পারে , এবং force_encoding
হবে না।
এনকোডিং বাগগুলি ঠিক করার জন্য একটি তিন-পদক্ষেপ প্রক্রিয়া
আপনি তিনটি ধাপে বেশিরভাগ এনকোডিং সমস্যা সমাধান করতে পারেন:
1. আপনার স্ট্রিং কোন এনকোডিং আসলে তা আবিষ্কার করুন মধ্যে।
এই সহজ শোনাচ্ছে. কিন্তু শুধুমাত্র একটি স্ট্রিং বলে এটি কিছু এনকোডিং, এর মানে এই নয় যে এটি আসলে:
irb(main):078:0> "hi\x99!".encoding
=> #<Encoding:UTF-8>
এটা ঠিক নয় - যদি এটা সত্যিই হত UTF-8, এতে অদ্ভুত ব্যাকস্ল্যাশড নম্বর থাকবে না। তাহলে আপনি কিভাবে আপনার স্ট্রিং এর জন্য সঠিক এনকোডিং বের করবেন?
অনেক পুরানো সফ্টওয়্যার একটি একক ডিফল্ট এনকোডিংয়ে আটকে থাকবে, যাতে আপনি ইনপুটটি কোথা থেকে এসেছে তা গবেষণা করতে পারেন। কেউ কি Word থেকে পেস্ট করেছে? এটি Windows-1252 হতে পারে। এটি কি একটি ফাইল থেকে এসেছে বা আপনি এটি একটি পুরানো ওয়েবসাইট থেকে টানছেন? এটি ISO-8859-1 হতে পারে।
আমি এনকোডিং টেবিলের জন্য অনুসন্ধান করাও সহায়ক বলে মনে করেছি, যেমন সেই লিঙ্কযুক্ত উইকিপিডিয়া পৃষ্ঠাগুলিতে। এই টেবিলগুলিতে, আপনি অজানা সংখ্যা দ্বারা উল্লেখ করা অক্ষরগুলি সন্ধান করতে পারেন এবং দেখতে পারেন যে সেগুলি প্রসঙ্গে অর্থপূর্ণ কিনা৷
এই উদাহরণে, Windows-1252 চার্ট দেখায় যে বাইট 99
"™" অক্ষর প্রতিনিধিত্ব করে। বাইট 99
ISO-8859-1 এর অধীনে বিদ্যমান নেই। যদি ™ এখানে বোধগম্য হয়, আপনি অনুমান করতে পারেন যে ইনপুটটি Windows-1252-এ ছিল এবং এগিয়ে যান। অন্যথায়, আপনি গবেষণা চালিয়ে যেতে পারেন যতক্ষণ না আপনি এমন একটি চরিত্র খুঁজে পান যা আরও যুক্তিসঙ্গত বলে মনে হয়।
2. আপনি কোন এনকোডিং চান তা নির্ধারণ করুন৷ স্ট্রিং হতে হবে।
এই এক সহজ. আপনার কাছে একটি ভাল কারণ না থাকলে, আপনি আপনার স্ট্রিংগুলিকে UTF-8 এনকোড করতে চান৷
আপনি রুবিতে ব্যবহার করতে পারেন এমন একটি সাধারণ এনকোডিং রয়েছে:ASCII-8BIT। ASCII-8BIT-এ, প্রতিটি অক্ষর একটি একক বাইট দ্বারা উপস্থাপিত হয়। অর্থাৎ, str.chars.length == str.bytes.length
. সুতরাং, আপনি যদি আপনার স্ট্রিং-এর নির্দিষ্ট বাইটের উপর অনেক নিয়ন্ত্রণ চান, তাহলে ASCII-8BIT একটি ভাল বিকল্প হতে পারে।
3. ধাপ 1 এর এনকোডিং থেকে ধাপ 2 এর এনকোডিং পর্যন্ত আপনার স্ট্রিংটিকে পুনরায় এনকোড করুন৷
আপনি encode
দিয়ে এটি করতে পারেন পদ্ধতি এই উদাহরণে, আমাদের স্ট্রিং হয় Windows-1252 এনকোডিং-এ, এবং আমরা চাই এটি UTF-8 হয়ে যাবে। বেশ সোজা:
irb(main):088:0> "hi\x99!".encode("UTF-8", "Windows-1252")
=> "hi™!"
অনেক ভাল. (যদিও সেই কলে এনকোডিংয়ের ক্রমটি সর্বদা আমার কাছে পিছনের দিকে বলে মনে হয়)।
বাইটের একই অ্যারের বিভিন্ন ব্যাখ্যা কল্পনা করা মস্তিষ্ক-বাঁকানো হতে পারে। বিশেষ করে যখন সেই ব্যাখ্যাগুলির একটি ভেঙে যায়। কিন্তু এনকোডিংগুলির সাথে অনেক বেশি আরামদায়ক হওয়ার একটি দুর্দান্ত উপায় রয়েছে:তাদের সাথে খেলুন৷
একটি irb
খুলুন কনসোল, এবং encode
দিয়ে গোলমাল করুন , bytes
, এবং force_encoding
. কিভাবে encode
দেখুন স্ট্রিং তৈরি করে বাইট পরিবর্তন করে। বিভিন্ন এনকোডিং কেমন দেখায় সে সম্পর্কে অন্তর্দৃষ্টি তৈরি করুন। আপনি যখন এনকোডিংগুলির সাথে আরও স্বাচ্ছন্দ্য বোধ করেন এবং এই পদক্ষেপগুলি ব্যবহার করেন, তখন আপনি কয়েক ঘন্টা আগে যা নিতেন তা কয়েক মিনিটের মধ্যে ঠিক করে ফেলবেন৷
অবশেষে, আপনি যদি শিখতে চান যে কীভাবে এই ধরণের জিনিসগুলি শিখে অভ্যাস তৈরি করা যায়, আমার বইয়ের বিনামূল্যের নমুনা অধ্যায়টি ধরুন৷ কনসোলে জিনিস ভাঙা একটি সত্যিই এই মত ধারনা অধ্যয়ন করার মজার উপায়।