您的位置:首页 > 其它

VC Unicode工程读写文本文件

2010-12-27 23:45 204 查看
参考文章:http://blog.csdn.net/wuchen1004/archive/2010/08/03/5786537.aspx

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

因为Windows底层处理字符串是以Unicode形式处理的,所以现在一般使用VC开发软件时都选择Unicode的工程。

在Unicode工程中,读写文本文件就会有一个比较纠结的问题:

一般情况下我们新建和编辑的文本文件都是ANSI格式的,而在ANSI工程中用着十分方便的CStdioFile读取字符串时

使用的是CString类型, 这就导致Unicode工程环境下CStdioFile将Ansi的字符串读取到了CStringW类型中,

即使想使用CA2W来转, 也会出现类型不匹配的错误。

这种情况下,只好自己使用MultiByteToWideChar这类API来转换,实际编码时总是不太方便。但是即使使用这种方法还是

比直接使用ReadFile来读取文件要方便一些, 因为毕竟不需要自己处理换行。

目前来看Unicode工程环境下读取ansi文件最方便的还是使用fstream,这种方法不仅可以读取一行文本,还可以很方便的读取一行中的多个数字或者单词(参见后面的实例代码)。在CodeProject上有一篇文章,封装了两个读取ansi和unicode字符串的函数,他是直接使用fgetc和fgetwc来读取字符,这种方法本质上跟ReadFile差不多。

另外值得注意的是,一般情况下创建一个新文件都是Ansi类型的,要创建unicode文件需要在文件的前两个字节写入0xFFFE。

因为unicode文件开头这两个字节的原因,使用fstream读取unicode文件会有问题,请见代码示例。

int CCTextFile_TestDlg::CStdioFileTest(void)
{
CStdioFile	file;
CString		line;

// Read ANSI File
file.Open( _T( "test_ansi.txt" ), CFile::modeRead );
while ( file.ReadString( line ) )
{
OutputDebugString( line );		// 汉字乱码
}
file.Close();

// Read Unicode File
file.Open( _T( "test_unicode.txt" ), CFile::modeRead );
while ( file.ReadString( line ) )
{
OutputDebugString( line );		// 乱码
}
file.Close();

// 写文件, 得到的文件是ansi文件
file.Open( _T( "test_stdiofile.txt" ), CFile::modeCreate | CFile::modeWrite );
file.WriteString( _T( "CStdioFile Test:" ) );		// 成功
file.WriteString( _T( "测试Unicode!/n" ) );		// 写入失败

file.Close();

return 0;
}

int CCTextFile_TestDlg::StreamTest(void)
{
// 读取Ansi文件
std::ifstream	isin;
isin.open( _T( "test_ansi.txt" ), ios::in | ios::binary );
if ( isin )
{
// 读取一行
string	line;
getline( isin, line );
OutputDebugString( CA2W( line.c_str() ) );

// 读取 字符串 和 数字, 这是stream 读取文件的方便之处
string	line2;
int		row;

isin>>line2>>row;

CString tmp = CA2W( line2.c_str() );
tmp.AppendFormat( _T( " %d" ), row );
OutputDebugString( tmp );

isin.close();
}

// 读取Unicode 文件
std::wifstream	isinu;
isinu.open( _T( "test_unicode.txt" ), ios::in | ios::binary );
if ( isinu )
{
// 读取一行
wstring	line;
while ( getline( isinu, line ) )
{
OutputDebugString( line.c_str() );// 乱码, 读取失败, 因为 FFFE开头
}

isinu.close();
}

// 写一个ansi文件, 没有问题
ofstream	aof;
aof.open( _T( "test_ofstream.txt" ) );
if ( aof )
{
aof<<"stream ansi test第一行!"<<endl;
aof<<123<<"  "<<456<<endl;

aof.close();
}

// 写文件, 得到仍然是ansi文件, 写入英文成功
wofstream	of;
of.open( _T( "test_wofstream.txt" ) );
if ( of )
{
of<<_T( "stream unicode test第一行!" )<<endl;		// 写入汉字失败
of<<123<<L"  "<<456<<endl;

of.close();
}

return 0;
}

int CCTextFile_TestDlg::Line2FileTest(void)
{
FILE * fileAnsi = NULL;
FILE * fileUni = NULL;

// 读取Ansi文件
fileAnsi = fopen( "test_ansi.txt", "rb" );
if ( fileAnsi != NULL )
{
string	line;
while ( LineFromFile( fileAnsi, line ) )
{
OutputDebugString( CA2W( line.c_str() ) );
}
fclose( fileAnsi );
}

fileUni = fopen( "test_unicode.txt", "rb" );
if ( fileUni != NULL )
{
wstring	line;
while ( LineFromFile( fileUni, line ) )
{
// Unicode 文件开头的 FFEE被打印成了‘?’, 没有跳过
OutputDebugString( line.c_str() );
}
fclose( fileUni );
}

// 写一个Ansi文件
fileAnsi = fopen( "test_line_ansi.txt", "wb" );
if ( fileAnsi != NULL )
{
LineToFile( fileAnsi, "ansi file 第一行!" );
LineToFile( fileAnsi, "line 2" );
fclose( fileAnsi );
}

// 写文件, 得到的是ansi文件, 但是字符串是unicode编码的
fileUni = fopen( "test_line_unicode.txt", "wb" );
if ( fileUni != NULL )
{
LineToFile( fileUni, L"unicode file 第一行!" );		// 成功
LineToFile( fileUni, L"Line 2" );
fclose( fileUni );
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: