2012-03-25 10 views
11

मैं वर्तमान में एक एप्लिकेशन लिख रहा हूं जिसके लिए मुझे मनमाने ढंग से विंडोज़ पर GetWindowText को कॉल करने और बाद में प्रसंस्करण के लिए फ़ाइल को डेटा स्टोर करने की आवश्यकता है। लंबी कहानी संक्षेप में, मैंने देखा है कि मेरी उपकरण युद्धक्षेत्र 3 पर असफल रहा था, और मैं अपने विंडो शीर्षक में निम्नलिखित चरित्र के लिए नीचे समस्या संकुचित: http://www.fileformat.info/info/unicode/char/2122/index.htmविंडोज यूनिकोड सी ++ स्ट्रीम आउटपुट विफलता

तो मैं जो सिर्फ निम्नलिखित करता है एक छोटे से परीक्षण ऐप बनाया:

std::wcout << L"\u2122"; 

कम और निहारना है कि कार्यक्रम के शेष के लिए कंसोल विंडो के उत्पादन टूट जाता है।

एमएसवीसी एसटीएल इस चरित्र पर क्यों चकित कर रहा है (और मैं दूसरों को मानता हूं) जब MessageBoxW आदि जैसे एपीआई इसे ठीक दिखाते हैं?

मैं उन पात्रों को अपनी फ़ाइल में कैसे मुद्रित कर सकता हूं?

विंडोज 7 x64 के तहत वीसी 10 और वीसी 11 दोनों पर परीक्षण किया गया।

खराब निर्मित पोस्ट के लिए खेद है, मैं यहां अपने बालों को फाड़ रहा हूं।

धन्यवाद।

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

मिनिमल परीक्षण का मामला

#include <fstream> 
#include <iostream> 

int main() 
{ 
    { 
    std::wofstream test_file("test.txt"); 
    test_file << L"\u2122"; 
    } 

    std::wcout << L"\u2122"; 
} 

अपेक्षित परिणाम: '™' चरित्र को सांत्वना और फाइल करने के लिए मुद्रित। निरीक्षण परिणाम: फ़ाइल बनाई गई है लेकिन खाली है। कंसोल करने के लिए कोई आउटपुट नहीं।

मैं पुष्टि की है कि फॉन्ट मैं "मेरे कंसोल के लिए उपयोग कर रहा हूँ सवाल में चरित्र प्रदर्शित करने में सक्षम है, और निश्चित रूप से फ़ाइल खाली (आकार में 0 बाइट्स) है

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

आगे डिबगिंग पता चलता है कि 'failbit' और 'badbit' धारा (रों) में स्थापित कर रहे हैं

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

मैं भी Boost.Locale उपयोग करने की कोशिश की है और मैं भी नए स्थान के साथ एक ही मुद्दा हो रहा है वैश्विक स्तर पर और स्पष्ट रूप से सभी स्टैंड के लिए imbued ard धाराओं।

उत्तर

14

एक फ़ाइल में लिखने के लिए, आप भाषा को ठीक से सेट करने के लिए है, उदाहरण के लिए यदि आप उन्हें UTF-8 वर्णों के रूप में लिखना चाहते हैं, आप

const std::locale utf8_locale 
      = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>()); 
test_file.imbue(utf8_locale); 

जोड़ने के लिए आप जोड़ने के लिए इन 2 शामिल है फ़ाइलों

#include <codecvt> 
#include <locale> 

_setmode(_fileno(stdout), _O_U8TEXT); 
जोड़कर सांत्वना आप (इस खिड़कियों विशिष्ट है) सही मोड में सांत्वना सेट करने के लिए लिखने के लिए

(यदि आप यूटीएफ -8 का उपयोग करना चाहते हैं)।

#include <fcntl.h> 
#include <io.h> 

इसके अलावा आप सुनिश्चित करें कि आपके एक फ़ॉन्ट (जैसे उदाहरण ल्युसिडा कंसोल के लिए के रूप में) यूनिकोड का समर्थन करता है कि प्रयोग कर रहे हैं बनाने के लिए है:

यह आप जोड़ने के लिए के लिए इन 2 फ़ाइलें शामिल हैं। आप अपनी कंसोल विंडो के गुणों में फ़ॉन्ट बदल सकते हैं।

पूरा कार्यक्रम अब इस तरह दिखता है:

#include <fstream> 
#include <iostream> 
#include <codecvt> 
#include <locale> 
#include <fcntl.h> 
#include <io.h> 

int main() 
{ 

    const std::locale utf8_locale = std::locale(std::locale(), 
            new std::codecvt_utf8<wchar_t>()); 
    { 
    std::wofstream test_file("c:\\temp\\test.txt"); 
    test_file.imbue(utf8_locale); 
    test_file << L"\u2122"; 
    } 

    _setmode(_fileno(stdout), _O_U8TEXT); 
    std::wcout << L"\u2122"; 
} 
+1

खैर मैं शर्मिंदा हो जाऊंगा, यह बताते हुए कि यूटीएफ 8 लोकेल वास्तव में काम करता है ... अब क्यों बूस्ट बूस्ट नहीं है। लोकेल मेरे लिए ऐसा कर रहा है?मैंने दस्तावेज़ों को यह कहते हुए व्याख्या की कि यूटीएफ -8 को डिफ़ॉल्ट संकीर्ण एन्कोडिंग माना जाता है, और मैंने वैश्विक स्तर पर और सभी स्थैतिक धाराओं में लोकेल को प्रभावित किया है, तो क्या ... – RaptorFactor

2

क्या आप हमेशा std::wcout का उपयोग कर रहे हैं या आप कभी-कभी std::cout का उपयोग कर रहे हैं? इन्हें मिलाकर काम नहीं करेगा। बेशक, त्रुटि विवरण "चोकिंग" आप जो भी समस्या देख रहे हैं उस पर बिल्कुल नहीं कहता है। मुझे संदेह होगा कि फाइलों का उपयोग करने के लिए यह एक अलग समस्या है।

क्योंकि समस्या का कोई वास्तविक वर्णन नहीं है क्योंकि इसमें कुछ हद तक क्रिस्टल बॉल होता है, जिसके बाद समस्या को हिट करने के लिए अंधेरे में एक शॉट होता है ... चूंकि आप यूनिकोड वर्णों को फ़ाइल से प्राप्त करना चाहते हैं, तो सुनिश्चित करें कि फ़ाइल स्ट्रीम आप std::locale का उपयोग कर रहे हैं जिसका std::codecvt<...> पहलू वास्तव में उपयुक्त यूनिकोड एन्कोडिंग में परिवर्तित हो जाता है।

+0

मैं हमेशा विस्तृत प्रकार और APIs का उपयोग कर रहा हूँ। मेरे प्रश्न में पोस्ट की गई रेखा जितनी आसान है, मेरे प्लेटफ़ॉर्म पर भी विफल हो जाती है। यदि आप wofout के साथ wcout को प्रतिस्थापित करते हैं तो डिट्टो। – RaptorFactor

+0

मैंने न्यूनतम परीक्षण केस जोड़ा है। – RaptorFactor

+0

क्या आपने सत्यापित किया था कि 'std :: codecvt 'डिफ़ॉल्ट' std :: locale' द्वारा उपयोग किया जाता है, एक यूनिकोड जागरूक एन्कोडिंग का उपयोग करता है? बूस्ट में एक [यूटीएफ -8 पहलू] (http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/codecvt.html) लगता है। मुझे संदेह होगा कि आपके प्लेटफ़ॉर्म पर 'std :: wcout'' std :: basic_filebuf 'का उपयोग करता है यानी यह दोनों फाइलों के लिए काम करेगा और आउटपुट को दूंगा। –

2

मैंने अभी जीसीसी (संस्करण 4.4 के माध्यम से 4.4) और एमएसवीसी 10 का परीक्षण किया, जो सभी इस समस्या को प्रदर्शित करते हैं।

समान रूप से टूटा wprintf है, जो सी ++ स्ट्रीम एपीआई जितना छोटा है।

मैं भी अगर और कुछ नहीं विफलता पैदा कर रहा था देखने के लिए कच्चे Win32 एपीआई का परीक्षण किया है, और यह काम करता है:

#include <windows.h> 
int main() 
{ 
    HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE); 
    DWORD n; 
    WriteConsoleW(stdout, L"\u03B2", 1, &n, NULL); 
} 

कौन सा β लिखते कंसोल के लिए (आप ल्युसिडा कंसोल की तरह कुछ करने के लिए cmd के फ़ॉन्ट स्थापित कर दें तो) ।

निष्कर्ष: wchar_t आउटपुट बड़े सी ++ मानक लाइब्रेरी कार्यान्वयन दोनों में बहुत ही टूटा हुआ है।

+2

यह बहुत ही टूटा हुआ नहीं है, बस बहुत ही दस्तावेज है। –

+0

आप मेरे विकल्प क्या कहेंगे? कच्चे एपीआई का उपयोग करने के लिए एक पुनर्लेख में कोड की हजारों लाइनें शामिल होंगी। Boost.Locale समस्या को हल करने के लिए प्रतीत नहीं होता ... – RaptorFactor

+0

मेरे पास निकोलाई जोसुटिस '['सी ++ मानक पुस्तकालय'] (http://www.josuttis.com/libbook/) आसान नहीं है, लेकिन यह है विषय पर निश्चित पुस्तक। और इस बात पर विचार करते हुए कि IOStreams बिट को डाइटमार कुहल द्वारा सह-लिखित किया गया है;), यह आईओएसट्रीम में पूरी तरह से चरित्र रूपांतरण सामग्री को अच्छी तरह से कवर करता है। – MSalters

1

हालांकि विस्तृत चरित्र धाराएं यूनिकोड इनपुट के रूप में लेती हैं, वही नहीं जो वे आउटपुट के रूप में उत्पादित करते हैं - पात्र एक रूपांतरण के माध्यम से जाते हैं। यदि एन्कोडिंग में एक वर्ण का प्रतिनिधित्व नहीं किया जा सकता है जो यह परिवर्तित हो रहा है, तो आउटपुट विफल हो जाता है।

+0

ऐसा लगता है कि 'गलत' (बेहतर शब्द की कमी के लिए)। मुझे यकीन नहीं है कि मैं समझता हूं कि वास्तव में कैसे काम करना है/ठीक करने के लिए आप क्या कह रहे हैं ... – RaptorFactor

+0

मुझे नहीं लगता कि यह सच है, या तो। 'std :: wstringstream' निश्चित रूप से एक विस्तृत वर्ण धारा है (' std :: wstream' से विरासत), लेकिन कोई रूपांतरण नहीं करता है। – MSalters

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