2010-06-22 24 views
0

所有的時候,我使用setw爲我的ANSI文本文件對齊。最近,我想在我的文本文件中支持UTF-8。我發現setw不再有效。setw:對齊爲UTF-8文本文件

#include <windows.h> 
#include <iostream> 
// For StringCchLengthW. 
#include <Strsafe.h> 
#include <fstream> 
#include <iomanip> 
#include <string> 
#include <cassert> 

std::string wstring2string(const std::wstring& utf16_unicode) { 
    // 
    // Special case of NULL or empty input string 
    // 
    if ((utf16_unicode.c_str() == NULL) || (*(utf16_unicode.c_str()) == L'\0')) 
    { 
     // Return empty string 
     return ""; 
    } 

    // 
    // Consider WCHAR's count corresponding to total input string length, 
    // including end-of-string (L'\0') character. 
    // 
    const size_t cchUTF16Max = INT_MAX - 1; 
    size_t cchUTF16; 
    HRESULT hr = ::StringCchLengthW(utf16_unicode.c_str(), cchUTF16Max, &cchUTF16); 

    if (FAILED(hr)) 
    { 
     throw std::exception("Error during wstring2string"); 
    } 

    // Consider also terminating \0 
    ++cchUTF16; 

    // 
    // WC_ERR_INVALID_CHARS flag is set to fail if invalid input character 
    // is encountered. 
    // This flag is supported on Windows Vista and later. 
    // Don't use it on Windows XP and previous. 
    // 

    // CHEOK : Under Windows XP VC 2008, WINVER is 0x0600. 
    // If I use dwConversionFlags = WC_ERR_INVALID_CHARS, runtime error will 
    // occur with last error code (1004, Invalid flags.) 
//#if (WINVER >= 0x0600) 
// DWORD dwConversionFlags = WC_ERR_INVALID_CHARS; 
//#else 
    DWORD dwConversionFlags = 0; 
//#endif 

    // 
    // Get size of destination UTF-8 buffer, in CHAR's (= bytes) 
    // 
    int cbUTF8 = ::WideCharToMultiByte(
     CP_UTF8,    // convert to UTF-8 
     dwConversionFlags,  // specify conversion behavior 
     utf16_unicode.c_str(), // source UTF-16 string 
     static_cast<int>(cchUTF16), // total source string length, in WCHAR's, 
             // including end-of-string \0 
     NULL,     // unused - no conversion required in this step 
     0,      // request buffer size 
     NULL, NULL    // unused 
     ); 

    assert(cbUTF8 != 0); 

    if (cbUTF8 == 0) 
    { 
     throw std::exception("Error during wstring2string"); 
    } 

    // 
    // Allocate destination buffer for UTF-8 string 
    // 
    int cchUTF8 = cbUTF8; // sizeof(CHAR) = 1 byte 
    CHAR * pszUTF8 = new CHAR[cchUTF8]; 

    // 
    // Do the conversion from UTF-16 to UTF-8 
    // 
    int result = ::WideCharToMultiByte(
     CP_UTF8,    // convert to UTF-8 
     dwConversionFlags,  // specify conversion behavior 
     utf16_unicode.c_str(), // source UTF-16 string 
     static_cast<int>(cchUTF16), // total source string length, in WCHAR's, 
             // including end-of-string \0 
     pszUTF8,    // destination buffer 
     cbUTF8,     // destination buffer size, in bytes 
     NULL, NULL    // unused 
     ); 

    assert(result != 0); 

    if (result == 0) 
    { 
     throw std::exception("Error during wstring2string"); 
    } 

    std::string strUTF8(pszUTF8); 

    delete[] pszUTF8; 

    // Return resulting UTF-8 string 
    return strUTF8; 
} 

int main() { 
    // Write the file content in UTF-8 
    { 
     std::ofstream file; 
     file.open("c:\\A-UTF8.txt"); 
     file << std::setw(12) << std::left << wstring2string(L"我愛你") << "????" << std::endl; 
     file << std::setw(12) << std::left << "ILU" << "????"; 
    } 

    { 
     std::ofstream file; 
     file.open("c:\\A-ANSI.txt"); 
     file << std::setw(12) << std::left << "WTF" << "????" << std::endl; 
     file << std::setw(12) << std::left << "ILU" << "????"; 
    } 
    return 0; 
} 

我對A-ANSI.txt輸出

WTF   ???? 
ILU   ???? 

我放出來的A-UTF8.txt

我愛你 ???? 
ILU   ???? 

我怎樣才能讓A- UTF8.txt的文本是否正確對齊?

回答

0

我對此並不熟悉,但我猜出現的情況是:您仍然輸出12個字符,但這些字符的第一部分佔用較少的空間,因爲多個字符被分組爲一個Unicode符號。如果是這樣的話,你可以計算cout語句之前的差異並將其傳遞給setw。祝你好運。