2013-11-01 5 views
0

Я хочу читать и писать файлы utf-16, в которых используются разделители строк LL \ R \ n "). Использование C++ (Microsoft Visual Studio 2010) iostreams. Я хочу, чтобы каждый L "\ n" записывался в поток для трансляции в L "\ r \ n" прозрачно. Использование фрейма lococ codecvt_utf16 требует, чтобы открыть fstream в ios :: двоичном режиме, потеряв обычный текстовый режим \ n на \ r \ n перевод.C++ iostream UTF-16 файл ввода/вывода с CR LF translation

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();++ 

Я хочу решение без дополнительных библиотек, таких как BOOST.

+1

Вы используете Широкие галстуки. Широким символам не гарантируется UTF-16. Они тоже могут быть UTF-32. Поэтому не полагайтесь на них. Если вы используете C++, вместо этого используйте char16_t. – doptimusprime

+1

@dbasic Хотя 'char16_t' является правильным решением, поддержка C++ 11 (и, следовательно, тип' char16_t') в VS2010 очень невелика. –

+1

Не хватает примерно года, дайте или возьмите несколько месяцев. Конечно, их можно обвинить в том, что они не запрограммировали машину времени. –

ответ

1

Я думаю, что нашел решение самостоятельно, я хочу поделиться им. Ваши комментарии приветствуются!

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