简体   繁体   English

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

[英]C++ iostream UTF-16 file I/O with CR LF translation

I want to read and write utf-16 files which use CR LF line separators (L"\\r\\n"). 我想读写使用CR LF行分隔符(L“ \\ r \\ n”)的utf-16文件。 Using C++ (Microsoft Visual Studio 2010) iostreams. 使用C ++(Microsoft Visual Studio 2010)iostream。 I want every L"\\n" written to the stream to be translated to L"\\r\\n" transparently. 我希望将写入流的每个L“ \\ n”透明地转换为L“ \\ r \\ n”。 Using the codecvt_utf16 locale facet requires to open the fstream in ios::binary mode, losing the usual text mode \\n to \\r\\n translation. 使用codecvt_utf16语言环境方面要求在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();++

I want a solution without needing extra libraries like BOOST. 我想要一个不需要BOOST之类的额外库的解决方案。

I think I've found a solution myself, I want to share it. 我想自己找到了一个解决方案,我想分享一下。 Your comments are welcome! 欢迎您发表评论!

#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();
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM