c++ - 为什么我用 WriteFile 写入文件的每个字符之间都有一个空白?

标签 c++ windows winapi unicode

这是我的代码:

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

我用 OPEN_ALWAYS 模式创建了这个文件,我将向这个文件写入一些常量字符串。该文件显示“ReplaceFile”,如下所示: 替换文件。

有人能告诉我如何让它正常吗?为什么? 提前致谢。

最佳答案

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;

关于c++ - 为什么我用 WriteFile 写入文件的每个字符之间都有一个空白?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31757798/

相关文章:

c++ - 为什么可能丢失数据的赋值不产生编译器警告

c++ - 如何从驱动器号中获取驱动器名称?

c++ - 阵列包装损坏堆

c++ - 调用纯虚方法——交叉编译

python - 如何检查 PyObject 是否为列表?

windows - 是否有检测操作系统的宏...?

c - getenv() 找不到我手动设置的环境变量(我是用 C 编写的)

c# - 将 C# 应用程序从 WinXP 转换为 7 : How to make it not require admin privileges?

c++ - 屏幕上的客户端矩形坐标

c - 如何读取子进程的输出?