2017-09-19 18 views
9

यहां एक समस्या है जिसे मैं अपने सभी प्रयासों के बावजूद हल नहीं कर सका। तो मैं पूरी तरह से अटक गया हूँ, कृपया मदद करें!यूटीएफ -16 स्ट्रीम में गलत सीआरएलएफ?

नियमित, "ASCII" मोड के लिए निम्नलिखित सरल फ़ाइल और धारा outputs

FILE *fa = fopen("utfOutFA.txt", "w"); 
fprintf(fa, "Line1\nLine2"); 
fclose(fa); 
ofstream sa("utfOutSA.txt"); 
sa << "Line1\nLine2"; 
sa.close(); 

परिणाम, स्वाभाविक रूप से, ठीक उसी पाठ फ़ाइलों में (हेक्स डंप):

00000000h: 4C 69 6E 65 31 0D 0A 4C 69 6E 65 32    ; Line1..Line2 

जहां नई लाइन \n को सीआरएलएफ में विस्तारित किया गया है: 0D 0A - विंडोज के लिए विशिष्ट।

अब, हम यूनिकोड आउटपुट के लिए ऐसा करते हैं, अर्थात् यूटीएफ -16 ली जो एक प्रकार का "डिफ़ॉल्ट" है। फ़ाइल उत्पादन

FILE *fu = fopen("utfOutFU.txt", "w, ccs=UNICODE"); 
fwprintf(fu, L"Line1\nLine2"); 
fclose(fu); 

परिणाम इस सामग्री में:

00000000h: FF FE 4C 00 69 00 6E 00 65 00 31 00 0D 00 0A 00 ; ÿþL.i.n.e.1..... 
00000010h: 4C 00 69 00 6E 00 65 00 32 00     ; L.i.n.e.2. 

जो बीओएम और endianness, CRLF सहित पर विचार पूरी तरह से सही लगती है: 0D 00 0A 00। हालांकि, इसी तरह धारा उत्पादन एक बाइट में

wofstream su("utfOutSU.txt"); 
su.imbue(locale(locale::empty(), new codecvt_utf16<wchar_t, 0x10ffffUL, 
          codecvt_mode(generate_header + little_endian)>)); 
su << L"Line1\nLine2"; 
su.close(); 

परिणामों ने कम से समग्र गलत पाठ फ़ाइल:

00000000h: FF FE 4C 00 69 00 6E 00 65 00 31 00 0D 0A 00 4C ; ÿþL.i.n.e.1....L 
00000010h: 00 69 00 6E 00 65 00 32 00      ; .i.n.e.2. 

कारण CRLF के गलत विस्तार है: 0D 0A 00। क्या यह एक बग है? या मैंने कुछ गलत किया है?

मैं माइक्रोसॉफ्ट विजुअल स्टूडियो कंपाइलर (14.0 और अन्य) का उपयोग करता हूं। मैंने \n के बजाय स्ट्रीम endl का उपयोग करने का प्रयास किया - एक ही परिणाम! मैंने su.imbue() पहले और फिर su.open() डालने की कोशिश की - सब वही! 0D 0A

मैं इस मुद्दे पर किसी भी विचार और टिप्पणियों की सराहना: CRLF के रूप में कोई समस्या नहीं ASCII मोड में के रूप में ही रहता है - मैं भी UTF-8 निर्गम (फ़ाइल के लिए ccs=UTF-8 और codecvt_utf8 स्ट्रीम के लिए) की जाँच की।

+0

यह शायद एक बग है, क्योंकि यूटीएफ -16 में बाइट्स की विषम संख्या नहीं हो सकती है। – CAF

उत्तर

2

जब आप imbue()std::wofstream में एक नया लोकेल डाल रहे हैं, तो आप अपना मूल लोकेल मिटा रहे हैं। locale::empty() का उपयोग न करें, इसके बजाय su.getloc() का उपयोग करें, इसलिए नया लोकेल इसे संशोधित करने से पहले पुराने लोकेल की प्रतिलिपि बनाता है।

इसके अलावा, एक तरफ ध्यान दें, codecvt_utf16 का अंतिम टेम्पलेट पैरामीटर बिटमैस्क है, इसलिए codecvt_mode(generate_header + little_endian) वास्तव में std::generate_header | std::little_endian होना चाहिए।

su.imbue(std::locale(su.getloc(), new codecvt_utf16<wchar_t, 0x10ffffUL, 
          std::generate_header | std::little_endian>)); 
+1

'+' और '|' के बीच कोई अंतर नहीं है जब प्रत्येक ऑपरेंड में बिट्स ओवरलैप नहीं होते हैं, लेकिन आपका बिंदु एक अच्छा है। –

+0

मुझे 'getloc() 'दिखाने के लिए धन्यवाद - मैं इस क्षेत्र में बहुत नौसिखिया हूं। – lariona

+0

कोडेकैट मोड के लिए, मेरे पास शुरुआती चरण में '|' था; फिर संकलक 'त्रुटि C2440:' विशेषज्ञता 'के साथ संघर्ष करते समय इसे '+' में बदल दिया:' int 'से' std :: codecvt_mode'' में परिवर्तित नहीं किया जा सकता; फिर अंततः एक स्पष्टीकरण कास्ट जोड़ना पड़ा, लेकिन उसे वापस '| 'में बदलने के लिए उपेक्षित किया गया। फिर भी धन्यवाद। – lariona

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