关于宽字节 Unicode与ANSI的学习体会 [WriteFile写TXT文件乱码解决]

7b20a2d2f703918f914b2e6d513d269758eec48c

做u盘程序绑定(u盘作为加密狗)开发时整理的。

 

TXT文件默认用的ANSI编码(简体中文系统下,ANSI 编码代表GB2312 编码),VS2005用WriteFile写入文件的时候,默认Unicode编码,比如“你”就是4F60,TXT文件打开的时候会认为是ANSI编码,产生乱码,但是如果中间英文或者数字的话,比如"a你",就变成00614F60,这样的话系统就会认为是Unicode编码,打开不会有乱码。

解决的方法有俩种:

1、在写入前插入0xFEFF,让系统认为是Unicode编码。注意,写入后用十六进制编辑器查看高低位是互换的

Unicode:0xFEFF
UTF8:0xEFBBBF

2、用WideCharToMultiByte函数将Unicode强制转换成ANSI双字节编码,比如“你”的Unicode编码4F60变成ANSI的E3C4,可以通过查询GB2312表得到证明

记录例子备忘:

if (LOWORD(wParam) == IDC_WRITE) //写入文件
{
TCHAR szTextAnsi[MAX_PATH];
HANDLE hFile;
hFile = CreateFile(szTextSource, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//这是一种解决乱码的方法,在前面写入0xfeff,以unicode方式打开
//      WORD a = 0xfeff;//写入0xfeff让记事本以Unicode方式打开,中文不会乱码
//      WriteFile(hFile, &a, 2, &dwBytesWrite, NULL);
//      if (WriteFile(hFile, szText,dwNumText*2, &dwBytesWrite, NULL))//第三个参数是写入的byte数,因为是宽字符,所以个数要乘以2

//第二种方法,宽窄字符转化
int a = WideCharToMultiByte(CP_ACP, NULL, szText, -1, LPSTR(szTextAnsi), MAX_PATH, NULL, FALSE);//Unicode转换为ANSI,a的值包括了字符串最后的0
if (WriteFile(hFile, szTextAnsi,a-1, &dwBytesWrite, NULL))//写入的时候最后的0不用写入所以要用a-1
{
MessageBox(hwnd,TEXT("写入成功"),TEXT("成功"),0);
}
else
{
MessageBox(hwnd,TEXT("写入失败"),TEXT("出错"),0);
}
CloseHandle(hFile);
break;
}