//原来一直用C中wfopen,putwc这些东西写unicode的文件
//一直没发现用wstring,wchar_t 的方法。
//最近在下面这个位置,发现一个好东西。
//http://www.codeproject.com/vcpp/stl/upgradingstlappstounicode.asp?df=100&forumid=16224&exp=0&select=788194
#include <locale>
#include <stdlib.h>
#include <TCHAR.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
using std::codecvt ;
typedef codecvt < wchar_t , char , mbstate_t > NullCodecvtBase ;
class NullCodecvt
: public NullCodecvtBase
{
public:
typedef wchar_t _E ;
typedef char _To ;
typedef mbstate_t _St ;
explicit NullCodecvt( size_t _R=0 ) : NullCodecvtBase(_R) { }
protected:
virtual result do_in( _St& _State , const _To* _F1 , const _To* _L1 , const _To*& _Mid1 ,
_E* F2 , _E* _L2 , _E*& _Mid2 ) const
{
return noconv ;
}
virtual result do_out( _St& _State ,
const _E* _F1 , const _E* _L1 , const _E*& _Mid1 ,
_To* F2, _E* _L2 , _To*& _Mid2 ) const
{
return noconv ;
}
virtual result do_unshift( _St& _State ,
_To* _F2 , _To* _L2 , _To*& _Mid2 ) const
{
return noconv ;
}
virtual size_t do_length( _St& _State , const _To* _F1 ,
const _To* _L1 , size_t _N2 ) const _THROW0()
{
return (_N2 < (size_t)(_L1 - _F1)) ? _N2 : _L1 - _F1 ;
}
virtual bool do_always_noconv() const _THROW0()
{
return true ;
}
virtual int do_max_length() const _THROW0()
{
return 2 ;
}
virtual int do_encoding() const _THROW0()
{
return 2 ;
}
} ;
#define IMBUE_NULL_CODECVT( outputFile ) \
{ \
NullCodecvt* pNullCodecvt = new NullCodecvt ; \
locale loc = locale::classic() ; \
loc._Addfac( pNullCodecvt , NullCodecvt::id, NullCodecvt::_Getcat() ) ; \
(outputFile).imbue( loc ) ; \
}
///自己随便以下写个测试,提醒一下自己别忘了
int main()
{
string str1="abc中文Chinese与英文English混排ss,,mbstowcs转换";
string str="efg中文Chinese与英文English混排ss\",,MultiByteToWideChar转换";
wstring str2=L"真是折腾人阿!!!";
wchar_t wst[100]={};
char czz[101]="Begin被替换End";
WCHAR tx1[100]={}; // TCHAR
cout<<str<<endl;
cout<<czz<<endl;
locale loc(""),oldloc;
setlocale(LC_ALL,""); //设置本地默认
// setlocale(LC_ALL,"CHS"); //直接指定本地
mbstowcs(wst, str1.c_str(), str1.size()+1);
setlocale(LC_ALL,"C"); //恢复默认
cout<<czz<<endl; //不恢复的话,这里输出貌似就出问题了。
setlocale(LC_ALL,""); //设置本地默认
lstrcpy(wst,str2.c_str());
wcstombs(czz,str2.c_str(),sizeof(czz));
setlocale(LC_ALL,"C"); //用完恢复
strcpy(czz,"Begin被替换End");
MultiByteToWideChar( CP_ACP,0, str.c_str(),strlen(str.c_str())+1, tx1,sizeof(tx1)/sizeof(tx1[0]));
WideCharToMultiByte(CP_ACP,0,tx1,lstrlen(tx1)+1,czz,sizeof(czz)/sizeof(czz[0]),NULL,NULL);
oldloc=wcout.imbue(loc); //设置,,如果不进行设置,输出将不正确
wcout<<endl;
wcout<<tx1<<endl;
wcout<<wst<<endl;
cout<<czz<<endl;
wcout<<str2<<endl;
wcout<<"the end"<<endl;
wcout.imbue(oldloc); //恢复
//建一个Unicode的文本文件存储之。
wofstream UniFile;
UniFile.open("C:\\uinFile.txt",ios::out|ios::binary); //
UniFile<<UniFile.narrow(0xFF); //设置Unicode文本文件标志.这两个是窄字符
UniFile<<UniFile.narrow(0xFE);
IMBUE_NULL_CODECVT( UniFile ) ;
//为什么要用这个,原来写入文件时字符被默认的本地化对象转换为nawwow了。所以总是不成功。
//现在通过这一步,让流使用自定义的本地对象进行对应的转换。
UniFile<<wst<<UniFile.widen('\r')<<UniFile.widen('\n'); //使用回车换行都要宽字符化。
UniFile<<tx1<<UniFile.widen('\r')<<UniFile.widen('\n');
UniFile<<str2<<UniFile.widen('\r')<<UniFile.widen('\n');
//UniFile.imbue(loc);
UniFile.close();
system("pause");
return 0;
}