目前共有5篇帖子。 內容轉換:不轉換▼
 
點擊 回復
375 4
【代码】将wchar_t字符数组直接写入txt文件的方法
一派護法 十九級
1樓 發表于:2016-1-24 11:56

【说明】
在Windows操作系统下,wchar_t的大小是两个字节,其默认的编码方式是UTF-16(Unicode的一种存储方式)。其中,每个基本多语言平面字符占据两个字节,也就是一个wchar_t数组元素;每个辅助平面字符占据四个字节,即两个wchar_t数组元素。例如,字符“长”是基本多语言平面字符,而“卒瓦”这两个字合在一起的那个汉字就是一个辅助平面字符(这个字符目前在Arslanbar还无法发表)。注意,如果用wcslen函数测定wchar_t字符数组的长度,数组中的每个辅助字符将会被认为是两个字符。
为了能让文本编辑器识别写入的txt文件是UTF-16编码格式,必须在文件开头写入两个字节的BOM作为标记(对于UTF8则是三个字节的BOM,不过这个BOM是可写可不写的)。UTF-16分为大尾序和小尾序两种格式,其BOM分别是0xFEFF和0xFFFE。在Windows和Linux系统上一般使用小尾序,而在Mac系统上则一般使用大尾序。在C++中我们可以用一个char字符数组存储这个BOM,然后写入txt文件的开头。
【代码】
wchar_t wstr[] = L"Windows操作系统内核中的字符表示为UTF-16小尾序,可以正确处理、显示以4字节存储的字符。但是Windows API实际上仅能正确处理UCS-2字符,即仅以2字节存储的,码位小于U+FFFF的Unicode字符。其根源是Microsoft C++语言把wchar_t数据类型定义为16比特的unsigned short,这就与一个wchar_t型变量对应一个宽字符,可以存储一个Unicode字符的规定相矛盾。相反,Linux平台的GCC编译器规定一个wchar_t是4字节长度,可以存储一个UTF-32字符,宁可浪费了很大的存储空间。下例运行于Windows平台的C++程序可说明此点。";
char bom[] = {0xff, 0xfe}; // UTF-16小尾序的BOM
wchar_t *pStr;
FILE *fp;
fopen_s(&fp, "utf16.txt", "wb"); // 打开文件
fwrite(bom, sizeof(bom), 1, fp); // 在文件头部写入BOM
for (pStr = wstr; *pStr != '\0'; pStr++)
    fwrite(pStr, sizeof(wchar_t), 1, fp); // 写入字符串,不写入末尾的\0
fclose(fp); // 关闭文件
【运行结果】

一派護法 十九級
2樓 發表于:2016-1-24 12:00

如果想要以UTF-8编码格式将wchar_t字符数组写入txt文件,就必须进行编码转换。一般使用WideCharToMultiByte函数进行转换。具体请参阅:
https://zh.arslanbar.net/post.php?t=23651
注:UTF-8是Unicode的另一种存储方式。
一派護法 十九級
3樓 發表于:2016-1-24 12:46

【代码】
读取UTF-16编码格式的txt文件的C++代码:
wchar_t wstr[300];
wchar_t *pStr = wstr;
FILE *fp;
fopen_s(&fp, "utf16.txt", "rb");
fseek(fp, 2, SEEK_SET); // 跳过文件开头两个字节的BOM
while (fread(pStr, sizeof(wchar_t), 1, fp), !feof(fp))
    pStr++; // 读取文件,直到文件结束
*pStr = '\0'; // 在wstr字符串末尾添加\0
::MessageBoxW(m_hWnd, wstr, L"文件内容", MB_ICONINFORMATION);
fclose(fp);
运行结果:

一派護法 十九級
4樓 發表于:2016-1-24 13:03

对于UTF-8文本文件,可以使用BOM也可以不使用BOM(三个字节),但Unicode标准既不推荐也不强制在UTF-8文本文件中使用BOM。
对于UTF-16文本文件,文件开头必须写入两个字节的BOM,并且要指定是使用小尾序还是大尾序。
一派護法 十九級
5樓 發表于:2016-1-24 13:08

Notepad++不能正确显示UTF-16中的辅助平面字符:

但是微软的记事本却可以:

而且,在Notepad++的右下角显示文本文件的编码格式为USC-2而非UTF-16:

UCS-2是UTF-16的子集。UCS-2不支持辅助平面字符,但是UTF-16既支持基本多语言平面字符,也支持辅助平面字符。

UTF-16 LE BOM:UTF-16小尾序,带BOM
UTF-16 BE BOM:UTF-16大尾序,带BOM

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:375 回複數:4
評論數: ?
作者: 巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2016-1-24 13:08
 
©2010-2024 Arslanbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。