C++ C++;iostream UTF-16带CR-LF转换的文件I/O

C++ C++;iostream UTF-16带CR-LF转换的文件I/O,c++,newline,iostream,utf-16,codecvt,C++,Newline,Iostream,Utf 16,Codecvt,我想读写使用CR LF行分隔符(L“\r\n”)的utf-16文件。使用C++(微软Visual Studio 2010)IOFSUBES。我希望写入流的每个L“\n”都能透明地转换为L“\r\n”。使用codecvt_utf16 locale方面需要以ios::binary模式打开fstream,从而丢失通常的文本模式\n到\r\n转换 std::wofstream wofs; wofs.open("try_utf16.txt", std::ios::binary); wofs.imbue(

我想读写使用CR LF行分隔符(L“\r\n”)的utf-16文件。使用C++(微软Visual Studio 2010)IOFSUBES。我希望写入流的每个L“\n”都能透明地转换为L“\r\n”。使用codecvt_utf16 locale方面需要以ios::binary模式打开fstream,从而丢失通常的文本模式\n到\r\n转换

std::wofstream wofs;
wofs.open("try_utf16.txt", std::ios::binary);
wofs.imbue(
    std::locale(
        wofs.getloc(),
        new std::codecvt_utf16<wchar_t, 0x10ffff, std::generate_header>));
wofs << L"Hi!\n"; // i want a '\r' to be inserted before the '\n' in the output file
wofs.close();++
std::wofstream-wofs;
open(“try_utf16.txt”,std::ios::binary);
浸透(
std::locale(
wofs.getloc(),
新标准:编解码器(VT_utf16));

wofs我想我自己已经找到了一个解决方案,我想与大家分享。欢迎您的评论

#include <iostream>
#include <fstream>

class wcrlf_filebuf : public std::basic_filebuf<wchar_t>
{
    typedef std::basic_filebuf<wchar_t> BASE;
    wchar_t awch[128];
    bool bBomWritten;
public:
    wcrlf_filebuf() 
        : bBomWritten(false)
    { memset(awch, 0, sizeof awch); }

    wcrlf_filebuf(const wchar_t *wszFilespec, 
                  std::ios_base::open_mode _Mode = std::ios_base::out) 
        : bBomWritten(false)
    {
        memset(awch, 0, sizeof awch);
        BASE::open(wszFilespec, _Mode | std::ios_base::binary);
        pubsetbuf(awch, _countof(awch));
    }

    wcrlf_filebuf *open(const wchar_t *wszFilespec, 
                        std::ios_base::open_mode _Mode = std::ios_base::out)
    {   
        BASE::open(wszFilespec, _Mode | std::ios_base::binary);
        pubsetbuf(awch, _countof(awch));
        return this;
    }

    virtual int_type overflow(int_type ch = traits_type::eof())
    {
        if (!bBomWritten) {
            bBomWritten = true;
            int_type iRet = BASE::overflow(0xfeff);
            if (iRet != traits_type::not_eof(0xfeff)) return iRet;
        }
        if (ch == '\n') {
            int_type iRet = BASE::overflow('\r');
            if (iRet != traits_type::not_eof('\r')) return iRet;
        }
        return BASE::overflow(ch);
    }
};

class wcrlfofstream : public std::wostream
{
    typedef std::wostream BASE;
public:
    wcrlfofstream(const wchar_t *wszFilespec, 
                  std::ios_base::open_mode _Mode = std::ios_base::out) 
        : std::wostream(new wcrlf_filebuf(wszFilespec, _Mode))
    {}

    wcrlf_filebuf* rdbuf()
    {
        return dynamic_cast<wcrlf_filebuf*>(std::wostream::rdbuf());
    }

    void close()
    {
        rdbuf()->close();
    }
};
#包括
#包括
类wcrlf_filebuf:public std::basic_filebuf
{
typedef std::basic_filebuf BASE;
wchar_t awch[128];
boolbomwrite;
公众:
wcrlf_filebuf()
:bbomwrited(false)
{memset(awch,0,sizeof awch);}
wcrlf_filebuf(常量wchar_t*wszFilespec,
std::ios\u base::open\u mode\u mode=std::ios\u base::out)
:bbomwrited(false)
{
memset(awch,0,awch的大小);
BASE::open(wszFilespec,|Mode | std::ios|u BASE::binary);
pubsetbuf(awch,_countof(awch));
}
wcrlf_filebuf*打开(常量wchar_t*wszFilespec,
std::ios\u base::open\u mode\u mode=std::ios\u base::out)
{   
BASE::open(wszFilespec,|Mode | std::ios|u BASE::binary);
pubsetbuf(awch,_countof(awch));
归还这个;
}
虚拟int_类型溢出(int_类型ch=traits_类型::eof())
{
如果(!bbomwrited){
bbomwrited=true;
int_type iRet=BASE::overflow(0xfeff);
if(iRet!=traits_type::not_eof(0xfeff))返回iRet;
}
如果(ch='\n'){
int_type iRet=BASE::overflow('\r');
如果(iRet!=traits\u type::not\u eof('\r'))返回iRet;
}
返回基::溢出(ch);
}
};
类wcrlfofstream:public std::wostream
{
typedef std::wostream BASE;
公众:
wcrlfofstream(常量wchar_t*wszFilespec,
std::ios\u base::open\u mode\u mode=std::ios\u base::out)
:std::wostream(新的wcrlf_filebuf(wszFilespec,_模式))
{}
wcrlf_filebuf*rdbuf()
{
返回动态_cast(std::wostream::rdbuf());
}
无效关闭()
{
rdbuf()->close();
}
};

您正在使用宽字符。宽字符不能保证为UTF-16。它们也可以是UTF-32。所以,不要依赖他们。如果你使用C++,则使用CHAR160T代替。@ dBasic,而代码> CAR16YT是正确的解决方案,VS2010中的C++ 11支持(因此 CHAR16VT 类型)非常缺乏。当然,他们可能会因为没有为时间机器编程而受到指责。@HansPassant虽然它确实是在标准发布之前制造的,但到那时,比赛确实有一些基于草稿的功能(最后几份草稿和最终规范之间的差异非常小)。@JoachimPileborg:true,但正如标准在功能完成后需要一段时间才能最终确定一样,VS2010也是如此。不过,我对VS2012不太宽容。