WinAPI编程的字符集和字符编码

WinAPI建议设为使用Unicode字符集(在工程属性里设置),也就是使用宽字符,然后使用MultiByteToWideChar和WideCharToMultiByte在宽字符和各种字符编码如GBK、UTF-8之间转换,GBK代码页是936,UTF-8代码页是65001。

文本文件建议使用UTF-8编码(字符乱码是非常显著的信号,所以不需要兼容所有字符编码),不过还是要兼容BOM以免Win10之前的用户困惑。

文件建议直接使用CreateFile打开读写,支持Unicode路径名。如遇到第三方库不能使用Unicode或UTF-8路径名,则使用GBK路径名也是可以的。

OpenCV4.0的imgcodecs模块,现在虽然imread/imwrite仍然只支持GBK文件名,但是imdecode/imencode已经重构过,不依赖临时文件了(可能是因为有人反馈Windows临时文件路径也可能包含Unicode字符),也就是说现在可以自己用CreateFile读文件,然后让imdecode解码,或者让imencode编码,然后用CreateFile写文件,这样可以添加Unicode路径名支持。

标准输入输出(stdin,stdout,stderr)建议还是使用GBK,这样的话可以允许用户在不改控制台字符编码的情况下显示字符,也可以正常使用重定向/管道功能。

如果需要显示GBK不能表示的字符,可以生成txt或html文件并打开以显示。如果需要编辑GBK不能表示的字符,可以首先生成一个带UTF-8 BOM的txt文件,再打开编辑并等待用户关闭记事本,即可获取输入。打开文件可以使用ShellExecute、ShellExecuteEx、CreateProcess等函数,也可以简单地用_wsystem、_wspawnlp。

注意系统有好几个虚拟代码页/代码页获取函数,但如果只有中文的话则不建议找麻烦,因为除936以外的代码页都不能正常显示简体中文,没有意义。不要考虑在控制台支持Unicode或UTF-8,微软已经承认这里有问题了,自己找麻烦得不偿失。

也不要学微软使用wprintf,微软使用这个函数的原因可能是英文Windows默认使用的1252代码页和C运行库没有setlocale之前使用的ISO-8859-1编码重合度较高,因此误以为不进行setlocale也能正常工作。使用wprintf要setlocale,这是个破坏兼容性的操作,建议尽量避免使用wprintf,自己转换。

获取函数 虚拟代码页

简体中文系统

典型西文系统

含义
GetACP() CP_ACP(0) 936(GBK)

英1252

俄1251

(系统级)ANSI版本WinAPI和C运行库的编码
GetOEMCP() CP_OEMCP(1) 936

英437/850

俄866

(系统级)OEM/DOS编码(很少使用)
GetConsoleCP()   936

英437/850

俄866

控制台输入编码,默认与OEM/DOS编码相同
GetConsoleOutputCP()   936

英437/850

俄866

控制台输出编码,正常情况下和输入编码相同,默认与OEM/DOS编码相同
  CP_UTF8(65001) 65001 65001 UTF-8
发布了29 篇原创文章 · 获赞 1 · 访问量 3414

猜你喜欢

转载自blog.csdn.net/defrag257/article/details/102759899