代码之家  ›  专栏  ›  技术社区  ›  Oystein

如何将std::wstring可移植地写入文件?

  •  18
  • Oystein  · 技术社区  · 15 年前

    我有一个 wstring 声明如下:

    // random wstring
    std::wstring str = L"abcàdëefŸg€hhhhhhhµa";
    

    文字应该是UTF-8编码的,因为我的源文件是。

    我非常想把它放到文件读取中(当文本编辑器设置为正确的编码时)

    abcàdëefŸg€hhhhhhhµa
    

    但是 ofstream 不太合作(拒绝接受 W环 参数),以及 wofstream 应该需要知道区域设置和编码设置。我只想输出这组字节。一个人通常怎么做?

    编辑:必须是跨平台的,并且 . 我刚好有一组字节存储在 W环 ,并希望输出它们。它很可能是UTF-16,或者纯ASCII。

    9 回复  |  直到 13 年前
        1
  •  7
  •   scigor    15 年前

    为什么不把文件写成二进制文件呢。只需在std::ios::binary设置中使用ofstream。编辑那时应该能够解释它。不要忘记开头的Unicode标志0xFEFF。 你最好用图书馆写作,试试下面这些:

    http://www.codeproject.com/KB/files/EZUTF.aspx

    http://www.gnu.org/software/libiconv/

    http://utfcpp.sourceforge.net/

        2
  •  33
  •   ST3    10 年前

    为了 std::wstring 你需要 std::wofstream

    std::wofstream f(L"C:\\some file.txt");
    f << str;
    f.close();
    
        3
  •  14
  •   Jerry Coffin    15 年前

    std::wstring 适用于UTF-16或UTF-32, UTF-8型。对于UTF-8,您可能只想使用 std::string ,并通过 std::cout . 只是FWIW,C++ 0x将有Unicode文字,这应该有助于澄清这种情况。

        4
  •  4
  •   Community Mohan Dere    9 年前

    C++有一种方法,可以在输出或文件写入中执行从宽字符到局部字符的转换。 Use 用于此目的的codecvt方面。

    你可以用标准 std::codecvt_byname implementation .

    #include <locale>
    using namespace std;
    typedef codecvt_facet<wchar_t, char, mbstate_t> Cvt;
    locale utf8locale(locale(), new codecvt_byname<wchar_t, char, mbstate_t> ("en_US.UTF-8"));
    wcout.imbue(utf8locale);
    wcout << L"Hello, wide to multybyte world!" << endl;
    

    并从列出的许多自定义codecvt实现的引用中进行选择。

    编辑:

        5
  •  2
  •   Steve Townsend    15 年前

    有一个(特定于Windows的)解决方案应该适合您 here . 基本上,转换 wstring 转到UTF-8代码页,然后使用 ofstream .

    #include < windows.h >
    
    std::string to_utf8(const wchar_t* buffer, int len)
    {
            int nChars = ::WideCharToMultiByte(
                    CP_UTF8,
                    0,
                    buffer,
                    len,
                    NULL,
                    0,
                    NULL,
                    NULL);
            if (nChars == 0) return "";
    
            string newbuffer;
            newbuffer.resize(nChars) ;
            ::WideCharToMultiByte(
                    CP_UTF8,
                    0,
                    buffer,
                    len,
                    const_cast< char* >(newbuffer.c_str()),
                    nChars,
                    NULL,
                    NULL); 
    
            return newbuffer;
    }
    
    std::string to_utf8(const std::wstring& str)
    {
            return to_utf8(str.c_str(), (int)str.size());
    }
    
    int main()
    {
            std::ofstream testFile;
    
            testFile.open("demo.xml", std::ios::out | std::ios::binary); 
    
            std::wstring text =
                    L"< ?xml version=\"1.0\" encoding=\"UTF-8\"? >\n"
                    L"< root description=\"this is a naïve example\" >\n< /root >";
    
            std::string outtext = to_utf8(text);
    
            testFile << outtext;
    
            testFile.close();
    
            return 0;
    }
    
        6
  •  0
  •   user225312    15 年前

    注意,宽流只输出char*变量,所以您可能应该尝试使用 c_str() std::wstring 然后输出到文件中。那么它可能会起作用?

        7
  •  0
  •   towi    15 年前

    你应该 如果要编写可移植代码,请使用UTF-8编码的源文件。对不起的。

      std::wstring str = L"abcàdëefŸg€hhhhhhhµa";
    

    (我不确定这是否真的损害了标准,但我认为是的。但即便如此,为了安全,你也不应该。)

    std::ostream 不会起作用的。有很多方法可以转换 wstring 至UTF-8。我最喜欢的是 这个 International Components for Unicode

        8
  •  0
  •   snowdude    15 年前

    根据我处理不同字符编码的经验,我建议您只在加载时处理UTF-8,并节省时间。如果您尝试将内部表示存储在UTF-8中,那么您将面临一个痛苦的世界,因为单个字符可以是1字节到4之间的任何字符。因此,像strlen这样的简单操作需要查看每个字节来决定len,而不是分配的缓冲区(尽管可以通过查看字符序列中的第一个字节来优化,例如00..7f是单字节字符,c2..df表示2字节字符等)。

    当人们指的是UTF-16时,通常会提到“Unicode字符串”,而在Windows上wchar是一个固定的2字节。在Windows中,我认为wchar_t只是:

    typedef SHORT wchar_t;
    

    完整的UTF-32 4字节表示很少需要,而且非常浪费,下面是Unicode标准(5.0)对它的说明:

    简而言之,使用whcar_t作为您的内部表示,并在加载和保存时进行转换(除非您知道需要完整的Unicode,否则不要担心完整的Unicode)。

    关于执行实际转换,请查看ICU项目:

    http://site.icu-project.org/

        9
  •  0
  •   Some programmer dude    7 年前

    前段时间我也遇到过同样的问题,我在博客上写下了我找到的解决方案。你可能想看看它是否有用,尤其是函数 wstring_to_utf8

    http://pileborg.org/b2e/blog5.php/2010/06/13/unicode-utf-8-and-wchar_t