2010-02-23 11 views
14

मैं वर्तमान में एक एमएफसी प्रोग्राम पर काम कर रहा हूं जिसे विशेष रूप से यूटीएफ -8 के साथ काम करना है। किसी बिंदु पर, मुझे एक फ़ाइल में यूटीएफ -8 डेटा लिखना है; ऐसा करने के लिए, मैं CFiles और CStrings का उपयोग कर रहा हूँ।यूटीएफ -8, सीएसटींग और सीएफआईएल? (सी ++, एमएफसी)

जब मैं एक फ़ाइल में UTF-8 डेटा लिखने के लिए (रूसी वर्ण, और अधिक सटीक होना करने के लिए) मिलता है, उत्पादन की तरह

Ðàñïå÷àòàíî: 
Ñèñòåìà 
Ïðîèçâîäñòâî 

लग रहा है और आदि इस assurely utf-8 नहीं है। इस डेटा को सही तरीके से पढ़ने के लिए, मुझे अपनी सिस्टम सेटिंग्स बदलनी है; रूसी एन्कोडिंग तालिका में गैर ASCII वर्णों को बदलना काम करता है, लेकिन फिर मेरे सभी लैटिन आधारित गैर-असीसी वर्ण विफल हो जाते हैं। वैसे भी, मैं यह कैसे करता हूं।

CFile CSVFile(m_sCible, CFile::modeCreate|CFile::modeWrite); 
CString sWorkingLine; 
//Add stuff into sWorkingline 
CSVFile.Write(sWorkingLine,sWorkingLine.GetLength()); 
//Clean sWorkingline and start over 

क्या मुझे कुछ याद आ रही है? क्या मैं इसके बजाय कुछ और उपयोग करूँगा? क्या मुझे कुछ तरह का कैच याद आया है? मैं आपके ज्ञान और अनुभव, साथी प्रोग्रामर के लिए ट्यून किया जाएगा।

संपादित करें: बेशक, जैसा कि मैंने अभी एक प्रश्न पूछा है, मुझे अंततः कुछ दिलचस्प लगता है, जो here पाया जा सकता है। सोचा कि मैं इसे साझा कर सकता हूं।

संपादित करें 2:

ठीक है, तो मैं, मेरी फाइल है, जो अब chineese वर्ण को बीओएम जोड़ा शायद इसलिए क्योंकि मैं UTF-8 में मेरी लाइन में परिवर्तित नहीं किया। bom मैंने किया था ...

char BOM[3]={0xEF, 0xBB, 0xBF}; 
CSVFile.Write(BOM,3); 

और उसके बाद, मैं जोड़ा ...

TCHAR TestLine; 
    //Convert the line to UTF-8 multibyte. 
    WideCharToMultiByte (CP_UTF8,0,sWorkingLine,sWorkingLine.GetLength(),TestLine,strlen(TestLine)+1,NULL,NULL); 
    //Add the line to file. 
    CSVFile.Write(TestLine,strlen(TestLine)+1); 

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

संपादित करें 3:

तो, मैं इस कोड को ... जोड़ा

wchar_t NewLine[1000]; 
    wcscpy(NewLine, CT2CW((LPCTSTR) sWorkingLine)); 
    TCHAR* TCHARBuf = new TCHAR[1000]; 

    //Convert the line to UTF-8 multibyte. 
    WideCharToMultiByte (CP_UTF8,0,NewLine,1000,TCHARBuf,1000,NULL,NULL); 

    //Find how many characters we have to add 
    size_t size = 0; 
    HRESULT hr = StringCchLength(TCHARBuf, MAX_PATH, &size); 

    //Add the line to the file 
    CSVFile.Write(TCHARBuf,size); 

यह ठीक संकलित है, लेकिन जब मैं अपने नए फ़ाइल पर नज़र जाना है, यह के रूप में जब मैं नहीं था बिल्कुल वैसा ही है ' यह सब नया कोड नहीं है (उदा: Ðàñïå ÷ àòàíî :)। ऐसा लगता है जैसे मैंने एक कदम आगे नहीं किया, हालांकि मुझे लगता है कि केवल एक छोटी सी चीज़ मुझे जीत से अलग करती है।

संपादित करें 4:

मैं पहले, कोड जोड़ा हटाया के रूप में नैट पूछा, और मैं जिसका अर्थ है कि अब, जब मैं अपने पंक्ति जोड़ने के लिए मिलता है, मैं बजाय अपने कोड का उपयोग करने का फैसला किया, ...

 CT2CA outputString(sWorkingLine, CP_UTF8); 

    //Add line to file. 
    CSVFile.Write(outputString,::strlen(outputString)); 

सबकुछ ठीक से संकलित करता है, लेकिन रूसी वर्णों को ??????? के रूप में दिखाया जाता है। करीब आना, लेकिन अभी भी नहीं। बीटीडब्ल्यू, मैं उन सभी को धन्यवाद देना चाहता हूं जिन्होंने मेरी मदद करने की कोशिश की/कोशिश की, यह बहुत सराहना की है। मैं थोड़ी देर के लिए इस पर अटक गया हूं, मैं इस समस्या को समाप्त होने की प्रतीक्षा नहीं कर सकता।

अंतिम संपादन (मुझे आशा है) तरह से मैं पहली बार मिला है मेरी UTF-8 वर्णों (मैं वास्तव में जानने के बिना reencoded) है, जो पाठ outputting के अपने नए तरीके के साथ गलत था, मैं स्वीकार्य परिणाम मिल गया बदल कर।मेरी फ़ाइल की शुरुआत में यूटीएफ -8 बीओएम चार जोड़कर, इसे एक्सेल जैसे अन्य प्रोग्राम्स में यूनिकोड के रूप में पढ़ा जा सकता है।

Hurray! आप सभी को धन्यवाद!

+1

आपको एक टीसीएचएआर स्ट्रिंग की लंबाई प्राप्त करने के लिए _tcslen का उपयोग करने की आवश्यकता होगी। पसंद: \t टीसीएचएआर * testTCHAR = _T ("परीक्षण"); \t int tcharLength = _tcslen (testTCHAR); –

+1

यदि आपको CSTring को TCHAR * स्ट्रिंग में कनवर्ट करने की आवश्यकता है, तो यह \t CSTring testCString = _T ("test") को आजमाएं; \t टीसीएचएआर * testTCHAR = testCString.GetBuffer(); –

+0

आप बहुत मेहनत कर रहे हैं। 'CP_UTF8' के दूसरे पैरामीटर के साथ' CT2CA' का उपयोग करें। नीचे मेरी पोस्ट देखें। – Nate

उत्तर

24

आप आउटपुट डेटा आपको बस इतना करना है (यह मान लिया गया है आप यूनिकोड मोड है, जो अत्यधिक की सिफारिश की है में संकलन कर रहे हैं) की जरूरत है:

CString russianText = L"Привет мир"; 

CFile yourFile(_T("yourfile.txt"), CFile::modeWrite | CFile::modeCreate); 

CT2CA outputString(russianText, CP_UTF8); 
yourFile.Write(outputString, ::strlen(outputString)); 

तो _UNICODE परिभाषित नहीं है (यदि आप मल्टी-बाइट मोड में काम कर रहे हैं), आपको यह जानने की जरूरत है कि आपका इनपुट टेक्स्ट किस कोड पेज में है और इसे उस चीज़ में परिवर्तित करें जिसका आप उपयोग कर सकते हैं। इस उदाहरण रूसी पाठ UTF-16 के प्रारूप में है कि के साथ काम कर पता चलता है, UTF-8 में यह बचत:

// Example 1: convert from Russian text in UTF-16 (note the "L" 
// in front of the string), into UTF-8. 
CW2A russianTextAsUtf8(L"Привет мир", CP_UTF8); 
yourFile.Write(russianTextAsUtf8, ::strlen(russianTextAsUtf8)); 

अधिक संभावना है, अपने रूसी पाठ ऐसे KOI-8R रूप में कुछ अन्य कोड पृष्ठ में है। उस स्थिति में, आपको अन्य कोड पेज से यूटीएफ -16 में कनवर्ट करने की आवश्यकता है। फिर यूटीएफ -16 को यूटीएफ -8 में परिवर्तित करें। आप रूपांतरण मैक्रोज़ का उपयोग करके सीधे केओआई -8 आर से यूटीएफ -8 में परिवर्तित नहीं कर सकते हैं क्योंकि वे हमेशा संकीर्ण पाठ को सिस्टम कोड पेज में कनवर्ट करने का प्रयास करते हैं। तो आसान तरीका यह करने के लिए है:

// Example 2: convert from Russian text in KOI-8R (code page 20866) 
// to UTF-16, and then to UTF-8. Conversions between UTFs are 
// lossless. 
CA2W russianTextAsUtf16("\xf0\xd2\xc9\xd7\xc5\xd4 \xcd\xc9\xd2", 20866); 
CW2A russianTextAsUtf8(russianTextAsUtf16, CP_UTF8); 
yourFile.Write(russianTextAsUtf8, ::strlen(russianTextAsUtf8)); 

आप एक बीओएम की जरूरत नहीं है (यह वैकल्पिक है, मैं इसका इस्तेमाल नहीं होता जब तक कि वहाँ ऐसा करने के लिए एक विशेष कारण था)।

सुनिश्चित करें कि आप यह: http://msdn.microsoft.com/en-us/library/87zae4a3(VS.80).aspx पढ़ लें। यदि आप गलत तरीके से CT2CA का उपयोग करते हैं (उदाहरण के लिए, असाइनमेंट ऑपरेटर का उपयोग करके) आप परेशानी में भाग लेंगे। लिंक्ड प्रलेखन पृष्ठ उदाहरणों को दिखाता है कि इसका उपयोग कैसे करें और इसका उपयोग कैसे न करें।

अधिक जानकारी: CT2CA में

  • सीconst इंगित करता है। जब भी संभव हो मैं इसका उपयोग करता हूं, लेकिन कुछ रूपांतरण केवल गैर-कॉन्स संस्करण का समर्थन करते हैं (उदा। CW2A)।
  • टीCT2CA में इंगित करता है कि आप एक LPCTSTR से परिवर्तित कर रहे हैं। इस प्रकार यह काम करेगा कि आपका कोड _UNICODE ध्वज के साथ संकलित है या नहीं। आप CW2A (जहां डब्ल्यू विस्तृत वर्णों का संकेत भी दे सकते हैं)।
  • एकCT2CA में इंगित करता है कि आप एक "एएनएसआई" (8 बिट वर्ण) स्ट्रिंग के लिए परिवर्तित कर रहे हैं।
  • अंत में, CT2CA पर दूसरा पैरामीटर उस कोड पृष्ठ को इंगित करता है जिसे आप कनवर्ट कर रहे हैं।

(UTF-8 LPCTSTR तक) रिवर्स रूपांतरण करने के लिए, तुम कर सकते हो:

CString myString(CA2CT(russianText, CP_UTF8)); 

इस मामले में, हम UTF-8 में से परिवर्तित कर रहे हैं एक "एएनएसआई" स्ट्रिंग एक एलपीसीटीस्ट्रेट के लिए प्रारूप। LPCTSTR हमेशा यूटीएफ -16 माना जाता है (यदि _UNICODE परिभाषित किया गया है) या वर्तमान सिस्टम कोड पृष्ठ (यदि _UNICODE परिभाषित नहीं किया गया है)।

+0

मैंने कोशिश की कि आपने क्या कहा: मैंने बीओएम हटा दिया, और अपना कोड आपके लिए बदल दिया। अब, वर्णों को ??????? के रूप में दर्शाया गया है ??। कुछ अभी भी गायब है, शायद? मैं एक संपादन पोस्ट करूंगा। – SeargX

+0

प्रश्न चिह्न के रूप में प्रतिनिधित्व कहाँ? एक हेक्स संपादक का उपयोग कर परिणामी फ़ाइल देखें। आपको कुछ ऐसा देखना चाहिए [यह] (http://i.imgur.com/RcUsh.png)। और यदि आप इसे नोटपैड में खोलते हैं, तो आपको [this] (http://imgur.com/Yl3OU.png) देखना चाहिए। यदि नहीं, तो आपका मूल पाठ शायद सही ढंग से एन्कोड नहीं किया गया है। उम्मीद है कि आप '_UNICODE' परिभाषित कर रहे हैं और आपका इनपुट यूटीएफ -16 है। यदि नहीं, तो आपको वांछित कोड पृष्ठ पर मूल पाठ में जो कोड कोड है, उसे कनवर्ट करने के लिए मैक्रोज़ का उपयोग करने की आवश्यकता है। – Nate

+0

प्रश्न चिह्न परिणामस्वरूप फ़ाइल में हैं, और सभी के पास एक प्रश्न चिह्न हेक्स कोड (3 एफ, मुझे लगता है) है। मैं _UNICODE परिभाषित करने का उपयोग नहीं कर रहा हूं, और मुझे नहीं लगता कि यह एक अच्छा विचार होगा। मेरे द्वारा पढ़े गए रूसी वर्ण एक एक्सएमएल फ़ाइल से आते हैं, जिसे मैं tinyXML के साथ खोलता हूं, जो यूटीएफ -16, केवल यूटीएफ -8 और लैटिन 1 एन्कोडिंग पृष्ठों का समर्थन नहीं करता है। मुझे लगता है मुझे मैक्रोज़ का उपयोग करना है, हालांकि मैं उनसे परिचित नहीं हूं। – SeargX

6

आपको sWorkingLine को यूटीएफ -8 में परिवर्तित करना होगा और फिर इसे फ़ाइल में लिखना होगा।

WideCharToMultiByte यदि आप CP_UTF8 कोडपेज चुनते हैं तो यूनिकोड स्ट्रिंग्स को यूटीएफ -8 में परिवर्तित कर सकते हैं। MultiByteToWideChar ASCII वर्णों को यूनिकोड में परिवर्तित कर सकते हैं।

+0

ऐसे फ़ंक्शन का उपयोग करके, क्या सभी शामिल टेक्स्ट को एक से अधिक बाइट में बदल दिया जाएगा, या केवल गैर-असीसी वर्ण? – SeargX

+0

@SeargX, अगर आप यूटीएफ -8 का उपयोग करते हैं तो केवल गैर-असीसी। –

+0

डी: बिल्कुल सही, धन्यवाद। @Everyone मैं किस प्रकार की स्ट्रिंग को अपना परिवर्तित डेटा डालूं? TCHAR? मैं लाइन की लंबाई कैसे निर्धारित करूं, जिसे multibytetowidechar फ़ंक्शन में आवश्यक है? – SeargX

0

सुनिश्चित करें कि आप यूनिकोड (TCHAR wchar_t) का उपयोग कर रहे हैं। फिर डेटा लिखने से पहले, इसे WideCharToMultiByte Win32 API फ़ंक्शन का उपयोग करके परिवर्तित करें।

+0

'wchar_t' ** ** यूटीएफ -8 ** नहीं है, यह ** यूसीएस -2 ** है। – rhavin

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