【问题标题】:C++ / wcout / UTF-8C++ / wcout / UTF-8
【发布时间】:2013-09-11 18:21:37
【问题描述】:

我正在读取一个 UTF-8 编码的 unicode 文本文件,并将其输出到控制台,但显示的字符与我用于创建文件的文本编辑器中的不同。这是我的代码:

#define UNICODE

#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>

#include "pugixml.hpp"

using std::ifstream;
using std::ios;
using std::string;
using std::wstring;

int main( int argc, char * argv[] )
{
    ifstream oFile;

    try
    {
        string sContent;

        oFile.open ( "../config-sample.xml", ios::in );

        if( oFile.is_open() )
        {
            wchar_t wsBuffer[128];

            while( oFile.good() )
            {
                oFile >> sContent;
                mbstowcs( wsBuffer, sContent.c_str(), sizeof( wsBuffer ) );
              //wprintf( wsBuffer );// Same result as wcout.
                wcout << wsBuffer;
            }

            Sleep(100000);
        }
        else
        {
            throw L"Failed to open file";
        }
    }
    catch( const wchar_t * pwsMsg )
    {
        ::MessageBox( NULL, pwsMsg, L"Error", MB_OK | MB_TOPMOST | MB_SETFOREGROUND );
    }

    if( oFile.is_open() )
    {
        oFile.close();
    }

    return 0;
}

编码一定有一些我不明白的地方。

【问题讨论】:

    标签: c++ windows encoding utf-8


    【解决方案1】:

    问题在于 mbstowcs 实际上并不使用 UTF-8。它使用较旧的“多字节代码点”样式,与 UTF-8 不兼容(尽管在技术上 [我相信] 可以定义 UTF-8 代码页,但在 Windows 中没有这样的东西)。

    如果您想将 UTF-8 转换为 UTF-16,可以使用 MultiByteToWideChar,其中一个 codepageCP_UTF8

    【讨论】:

    • 谢谢,我试试这个!
    【解决方案2】:

    宽字符串并不意味着 UTF-8。事实上,恰恰相反:UTF-8 表示 Unicode 转换格式(8 位);这是一种在 8 位字符上表示 Unicode 的方法,所以你的正常 chars。您应该将其读入普通字符串(不是宽字符串)。

    宽字符串使用wchar_t,在 Windows 上是 16 位。操作系统使用 UTF-16 来实现其“宽”功能。

    在 Windows 上,可以使用 MultiByteToWideChar 将 UTF-8 字符串转换为 UTF-16。

    【讨论】:

    • 所以我需要将我的 UTF-8 文本转换为 UTF-16 以便 windows 可以使用它?
    • 大多数接受字符串的函数都可以用 A 或 W 作为后缀来指示字符串是 char 字符串还是 wchar_t 字符串。如果您的 API 只有宽字符串变体,是的,您需要转换。否则,这取决于函数是否接受 UTF-8(我不确定)。如果没有,你仍然需要转换,是的。
    【解决方案3】:

    我制作了一个 C++ char_t 容器,该容器最多可容纳 6 个 8 位 char_t,并将其存储在 std::vector 中。将其与wchar_t 相互转换或将其附加到std::string

    在这里查看: View UTF-8_String structures on Github

    #include "UTF-8_String.h" //header from github link above
    
    iBS::u8str  raw_v;
    iBS::readu8file("TestUTF-8File.txt",raw_v);
    std::cout<<raw_v.str()<<std::endl;
    

    这是将 wchar_t 转换为 uint32_t 在 u8char 结构体中喜欢的函数。

        #include <cwchar>
    
        u8char& operator=(wchar_t& wc)
        {
            char temp[6];
            std::mbstate_t state ;
            int ret = std::wcrtomb((&temp[0]), wc, &state);
            ref.resize(ret);
            for (short i=0; i<ret; ++i) 
                ref[i]=temp[i];
            return *this;
        };
    

    【讨论】:

      【解决方案4】:

      我发现wifstream 工作得很好,即使在Visual Studio 调试器中也能正确显示UTF-8 字(我正在阅读繁体中文字),来自this post

      #include <sstream>
      #include <fstream>
      #include <codecvt>
      
      std::wstring readFile(const char* filename)
      {
          std::wifstream wif(filename);
          wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
          std::wstringstream wss;
          wss << wif.rdbuf();
          return wss.str();
      }
       
      //  usage
      std::wstring wstr2;
      wstr2 = readFile("C:\\yourUtf8File.txt");
      wcout << wstr2;
      

      【讨论】:

        猜你喜欢
        • 2018-11-10
        • 1970-01-01
        • 2012-08-18
        • 1970-01-01
        • 1970-01-01
        • 2011-12-18
        • 2017-03-04
        • 2011-09-24
        • 1970-01-01
        相关资源
        最近更新 更多