为什么我用WriteFile写入文件的每个字符之间都有空格?

时间:2015-08-01 03:08:33

标签: c++ windows winapi unicode

这是我的代码:

WCHAR msg[] = L"ReplaceFile:";
::WriteFile( hFile, msg, lstrlenW(msg) * sizeof(WCHAR), &nBytes, NULL );  

我用OPEN_ALWAYS模式创建了这个文件,我要写一些const字符串到这个文件。该文件显示" ReplaceFile"像这样: R e p l a c e F i l e。

有人可以告诉我如何使其正常,为什么? 提前谢谢。

1 个答案:

答案 0 :(得分:4)

WCHARwchar_t的别名,在Windows上大小为2个字节。 Windows上的宽字符串以 UTF-16LE 编码。在UTF-16中,每个元素(称为代码单元)的大小为2字节(16位),其中Unicode代码点U-0000-U-FFFF占用一个代码单元,而较高代码点占用两个代码单元。

您的宽字符串仅包含 ASCII 字符,小于0x0080,因此每个字符使用不超过7位,至少将9位设置为0.因此,每隔一个字节写入该文件的值为0x00,这不是可显示的字符,因此您看到的额外间距。

您的宽字符串L"ReplaceFile:"由UTF-16LE中的以下字节组成:

0x52 0x00 // R
0x65 0x00 // e
0x70 0x00 // p
0x6C 0x00 // l
0x61 0x00 // a
0x63 0x00 // c
0x65 0x00 // e
0x46 0x00 // F
0x69 0x00 // i
0x6C 0x00 // l
0x65 0x00 // e
0x3A 0x00 // :

您应阅读以下文章:

The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

话虽如此,UTF-16不是将字符串存储在文件中的最佳选择。对于大多数语言,UTF-8比UTF-16更精简,并且它向后兼容ASCII。在Windows上,您可以使用WideCharToMultiByte()函数(或类似函数/库)转换宽字符串,然后再将其写入文件:

WCHAR msg[] = L"ReplaceFile:";
int len = WideCharToMultiByte(CP_UTF8, 0, msg, lstrlenW(msg), NULL, 0, NULL, NULL);
CHAR *converted = new CHAR[len];
WideCharToMultiByte(CP_UTF8, 0, msg, lstrlenW(msg), converted, len, NULL, NULL);
::WriteFile( hFile, converted, len * sizeof(CHAR), &nBytes, NULL );  
delete [] converted;