Warning C4819 & Error C2220问题的一种解决方法
问题描述
在使用visual studio工具的编译工具编译工程程序时, 出现大量warning C4819的警告和少量error C2220的错误,详细如下:
- warning C4819: The file contains a character that cannot be represented in the current code page(936). Save the file in Unicode format to prevent data loss
- error C2220: warning treated as error - no ‘object’ file generated
中文提示如下: - warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
- error C2220: 警告被视为错误 - 没有生成“object”文件
编译环境:
操作系统:Win10
Visual Studio 版本:2015
问题分析
若想搞清楚Warning的真实含义,就需要介绍其中提到的两个概念:Unicode 和 code page(详细介绍请自行查阅相关资料)。
- Unicode: 计算机科学领域里的一项业界标准,包括字符集、编码方案等。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
- codepage: (中文翻译成代码页),经过挑选的、以特定顺序排列的、用于代表字符的内码列表。用户在输入和存储文档时都要使用内码,内码分为单字节内码(SBCS)和多字节内码(DBCS)。codepage中的内码顺序使得系统可以按照此列表来根据键盘的输入值给出一个对应的内码(对于双字节内码,则给出的是MultiByte到Unicode的对应表)这样就可以把以Unicode形式存放的字符转化为相应的字符内码。
那么,Unicode和codepage是什么关系呢?在计算机发展早期,各国没有统一的编码方案,比如在中国大陆,较常用的编码格式有GBK18030、GBK、GB2312等。Unicode的出现,是将世界上所有的文字进行统一编码,形成Unicode编码集。此时codepage应运而生,codepage就是各国的文字编码和Unicode之间的映射表,比如简体中文和Unicode的映射表就是cp936,也就是warning中提到的代码页(936)或者code page(936)。
分析到这里,出现大量warning的问题就非常清楚了:我们所用的工程程序文件在代码编写时使用的非Unicode编码格式不是简体中文,但visual studio却使用编号为936( 即简体中文)的代码页对其进行映射(或翻译),并在其中发现了不能正确映射的字符,因此发出了警告。
而error C2220正是由这些不能正确映射的字符引起的,error比warning少很多的原因,猜测可能时因为只有错误映射的字符影响到程序编译时才报错,否则仅发出警告。
另,附上几个常用的codepage编号:
codepage编号 | non-unicode编码集 |
---|---|
936 | 简体中文GBK |
950 | 繁体中文BIG5 |
437 | 美国/加拿大英语 |
932 | 日文 |
949 | 韩文 |
866 | 俄文 |
1200 | UCS-2LE Unicode 小端序 |
1201 | UCS-2BE Unicode 大端序 |
65000 | UTF-7 Unicode |
65001 | UFT-8 Unicode |
问题解决
经上述分析,只要找对正确的code page,使程序工程的文件编码能够正确的被映射,即可解决该问题。
网上关于正确设置codepage的方法有以下几种,我将一一分析各种方法的优缺点及适用场景,并给出我自己的解决方法及适用场景:
方法一:
将所有被警告的文件转换为拥有正确code page编号的文件,一般转换为cp1200货cp65001即可。按照这种思路解决问题的方法不止一种,以下为我在网上看到的几篇博客和资料,仅供参考。
<点此观看使用本方法解决问题的他人博客1>
<点此观看使用本方法解决问题的他人博客2>
<点此观看Microsoft官方给出的解决方法>
该方法的优点是:设置简单,不破坏外部编码环境,缺点是不适用于文件较多的软件工程,每个都文件修改的时间成本太大。
方法二:
利用IDE环境,修改整个工程的属性,以下为Microsoft官网给出的解决方法:
<点此观看Microsoft官方给出的解决方法>
该方法主要适用对象为使用visual studio集成开发环境的用户,主要针对的问题是error 2220的消除,而非解决warning C4819,这可能是治标不治本的方法,能否解决程序编译及运行中的所有问题尚不得而知。
方法三(我所提供的方法):
修改大环境,使编译器使用与工程文件一致code page进行编译。白话讲,就是将win10系统默认的non-unicode编码格式修改为成工程文件相同。win10系统默认的non-unicode编码格式的修改步骤如下所示:
依次打开:计算机->控制面板(Control Panel Home)->区域(Region)->管理(Administrative)->更改系统区域设置(Change system locale),此时会弹出如下设置界面,将当前系统区域设置为英语(英国)即可。
该方法对拥有大量工程文件的程序效率极高,但它也有其固有的缺点,因为改变了电脑操作系统的整体设置,所以有可能导致一些中文文件显示乱码,因此是否需要使用该方法需要酌情考虑。