2009-08-13 7 views
12

जब मैं वाईफस्ट्रीम का उपयोग करके विस्तृत वर्ण स्ट्रिंग (std :: wstring) में एक टेक्स्ट फ़ाइल पढ़ता हूं, तो क्या स्ट्रीम कार्यान्वयन अलग-अलग एन्कोडिंग का समर्थन करता है - यानी इसे पढ़ने के लिए उपयोग किया जा सकता है। एएससीआईआईआई, यूटीएफ -8, और यूटीएफ -16 फाइलें?करता है (डब्ल्यू) ifstream अलग-अलग एन्कोडिंग का समर्थन करता है

यदि नहीं, तो मुझे क्या करना होगा?

+2

लोकेल के साथ स्ट्रीम कैसे लगाएं। http://stackoverflow.com/questions/207662/writing-utf16-to-file-in-binary-mode/208431#208431 –

उत्तर

21

सी ++ std::locale के साधन और पहलू std::codecvt द्वारा वर्ण एन्कोडिंग का समर्थन करता है। सामान्य विचार यह है कि locale ऑब्जेक्ट सिस्टम के पहलुओं का वर्णन करता है जो संस्कृति से संस्कृति, (मानव) भाषा से भाषा में भिन्न हो सकते हैं। इन पहलुओं को facet एस में विभाजित किया गया है, जो टेम्पलेट तर्क हैं जो परिभाषित करते हैं कि कैसे स्थानीयकरण-निर्भर वस्तुओं (I/O धाराएं शामिल हैं) का निर्माण किया जाता है। जब आप istream से पढ़ते हैं या ostream पर लिखते हैं, तो प्रत्येक वर्ण का वास्तविक लेखन लोकेल के पहलुओं के माध्यम से फ़िल्टर किया जाता है। पहलुओं में यूनिकोड प्रकारों के न केवल एन्कोडिंग को शामिल किया गया है, बल्कि इस तरह की विविध विशेषताएं हैं कि कितनी बड़ी संख्याएं लिखी गई हैं (जैसे अल्पविराम या अवधि), मुद्रा, समय, पूंजीकरण, और कई अन्य विवरण।

हालांकि सिर्फ इसलिए कि एन्कोडिंग करने के लिए सुविधाएं मौजूद हैं इसका मतलब यह नहीं है कि मानक पुस्तकालय वास्तव में सभी एन्कोडिंग को संभालता है, और न ही यह सही कोड करने के लिए सरल बनाता है। wchar_t बहुत छोटा हो सकता है (आपके डेटा को मैंगलिंग कर सकता है), या बहुत बड़ा (अंतरिक्ष बर्बाद कर रहा है), और सबसे आम कंपाइलर्स के रूप में आपको उस चरित्र के आकार के रूप में भी पढ़ना चाहिए (एन्कोडिंग भाग अकेला छोड़ना) मुश्किल है, उदाहरण के लिए विजुअल सी ++ और जीएनयू सी ++) उनके कार्यान्वयन पर कितना बड़ा है इस पर भिन्नता है। तो आपको वास्तविक एन्कोडिंग करने के लिए आम तौर पर बाहरी पुस्तकालयों को खोजने की आवश्यकता होती है।

  • iconv आम तौर पर है सही होने के लिए स्वीकार करते हैं, लेकिन कैसे सी ++ तंत्र के लिए यह बाध्य करने के उदाहरण मुश्किल है।
  • jla3ep mentionslibICU है, जो बहुत ही गहन है, लेकिन C++ API मानक के साथ अच्छी तरह से खेलने की कोशिश नहीं करता है (जहाँ तक मेरा बता सकते हैं:। आप examples स्कैन करते हैं तो आप बेहतर कर सकते हैं देखने के लिए कर सकते हैं)

सबसे सरल उदाहरण मैं पाया जा सकता है कि सभी अड्डों को कवर करता है, बूस्ट के UTF-8 codecvt facet से है, उदाहरण के लिए आईओ धाराओं द्वारा उपयोग के लिए विशेष रूप से यूटीएफ -8 (यूसीएस 4) को एन्कोड करने का प्रयास करता है। ऐसा लगता है, हालांकि मैं सुझाव नहीं देता कि इसे केवल क्रियात्मक रूप से कॉपी करें। यह लेता है एक छोटे से अधिक the source में खुदाई इसे समझने की (और मैं दावा नहीं करते):

typedef wchar_t ucs4_t; 

std::locale old_locale; 
std::locale utf8_locale(old_locale,new utf8_codecvt_facet<ucs4_t>); 

... 

std::wifstream input_file("data.utf8"); 
input_file.imbue(utf8_locale); 
ucs4_t item = 0; 
while (ifs >> item) { ... } 

स्थानों के बारे में अधिक समझने के लिए, और कैसे वे पहलुओं (codecvt सहित) का उपयोग, निम्नलिखित पर एक नज़र :

  • नाथन मायर्स के पास thorough explanation of locales and facets है। मायर्स लोकेल अवधारणा के डिजाइनरों में से एक था। यदि आप इसके माध्यम से जाना चाहते हैं तो उसके पास more formal documentation है।
  • अपाचे के मानक पुस्तकालय कार्यान्वयन (पूर्व में रोगवेव के) में full list of facets है।
  • निकोलाई जोसुटिस The C++ Standard Library अध्याय 14 विषय के प्रति समर्पित है।
  • एंजेलिका लैंगर और क्लाउस क्रेफ्ट की Standard C++ IOStreams and Locales एक पूरी किताब समर्पित करती है।
+1

अच्छा सारांश। आप अपनी पुस्तक सूची में http://www.amazon.com/dp/0201183951 जोड़ना चाहेंगे। मुझे पता है कि यह मुद्दा का सबसे गहन उपचार है। – sbi

+0

एसबीआई: सूची में पुस्तक जोड़ा गया। अच्छे लिंक के लिए धन्यवाद। – quark

1

विस्तृत चरित्र स्ट्रिंग और विस्तृत चरित्र धारा पूर्व दिनांकों UTF-8, UTF-16 और यूनिकोड के डिजाइन (मैं, पूरी फ़ाइल को पढ़ने के लिए है कि अगर एक फर्क नहीं पड़ता की जरूरत है)। यदि आप तकनीकी प्राप्त करना चाहते हैं, तो मानक स्ट्रिंग और मानक स्ट्रीम एएससीआईआई पर आवश्यक रूप से काम नहीं करती है (यह केवल मूल रूप से सभी कंप्यूटर ASCII का उपयोग करते हैं; आप संभावित रूप से एक ईबीसीडीआईसी मशीन कर सकते हैं)।

रेमंड चेन एक बार wrote a series illustrating how to work with different wide character stream/string types

4

ifstream फ़ाइल के एन्कोडिंग की परवाह नहीं करता है। यह सिर्फ फाइल से अक्षर (बाइट्स) पढ़ता है। wifstream विस्तृत बाइट्स (wchar_t) पढ़ता है, लेकिन यह अभी भी फ़ाइल एन्कोडिंग के बारे में कुछ भी नहीं जानता है। wifstream यूसीएस -2 के लिए पर्याप्त है - यूनिकोड के लिए निश्चित-लंबाई वर्ण एन्कोडिंग (प्रत्येक वर्ण दो बाइट्स के साथ दर्शाया गया है)।

आप यूनिकोड फ़ाइलों से निपटने के लिए आईबीएम ICU लाइब्रेरी का उपयोग कर सकते हैं।

यूनिकोड के लिए अंतर्राष्ट्रीय घटक (आईसीयू) एक परिपक्व, सी/सी के ++ पोर्टेबल सेट और यूनिकोड का समर्थन, सॉफ्टवेयर अंतर्राष्ट्रीयकरण (i18n) और वैश्वीकरण (G11N) के लिए जावा लाइब्रेरीज, सभी प्लेटफार्मों पर अनुप्रयोगों दे रही है एक ही परिणाम है ।

आईसीयू एक गैर-क्रिएटिव ओपन सोर्स लाइसेंस के तहत जारी किया गया है जो वाणिज्यिक सॉफ्टवेयर और अन्य ओपन सोर्स या मुफ्त सॉफ्टवेयर दोनों के साथ उपयोग के लिए उपयुक्त है।

+1

मुझे लगता है कि यह कहने के लिए थोड़ा और सही है कि 'ifstream' एन्कोडिंग पर abstracts। यह निम्न स्तर की सुविधाओं के माध्यम से इसका उपयोग करता है: लोकेशंस (मानक सी ++ के लिए), और ओएस या लाइब्रेरी विशिष्ट i18n फ़ंक्शंस। यानी 'ifstream' परवाह नहीं है, लेकिन आप इस मामले में क्या कहते हैं परवाह करते हैं। – quark

+3

'लोकेशंस' के पास यूनिकोड के एन्कोडिंग के साथ कुछ लेना देना नहीं है। जब आप लोकेल सेट कर रहे हों, तो आप केवल 'iostream' को संकेत दें कि इसे कंसोल पर प्रतीकों का प्रतिनिधित्व कैसे करना चाहिए। लेकिन आप * फ़ाइल * के एन्कोडिंग का पता नहीं लगा सकते हैं। और 'ifstream' का उपयोग कर यूटीएफ -8 से एएनएसआई को अलग करना असंभव है। –

संबंधित मुद्दे