我正在尝试使用 -finput-charset 编译器选项在 g++ 中编译 UTF-16BE C++ 源文件,但我总是遇到一堆错误。更多细节如下。
我的环境(在 CentOS Linux 中):
- g++:4.1.2
- 图标v:2.5
- Linux 语言(在终端中):LANG="en_US.UTF-8"
我的示例源文件(以 UTF-16BE 编码存储):
// main.cpp:
#include <iostream>
int main()
{
std::cout << "Hello, UTF-16" << std::endl;
return 0;
}
我的步骤:
- 我阅读了关于 -finput-charset 选项的 g++ 手册。 g++ 手册说:
-finput-charset=charset 设置输入字符集,用于从输入文件的字符集转换为GCC使用的源字符集。如果没有指定区域设置,或者 GCC 无法从区域设置中获取此信息,则默认为 UTF-8。这可以被语言环境或此命令行选项覆盖。目前,如果存在冲突,命令行选项优先。charset 可以是系统的“ iconv ”库例程支持的任何编码。
- 因此,我输入了如下命令:
g++ -finput-charset=UTF-16BE main.cpp
我得到了这些错误:
在 main.cpp:1 包含的文件中:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1: 错误:程序中出现“\342”错误
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1: 错误:程序中出现杂散“\274”
...(重复,很多,大约 4000+)...
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1: 错误:程序中出现杂散“\257”
main.cpp:在函数“int main()”中:
main.cpp:5:错误:“cout”不是“std”的成员
main.cpp:5:错误:“endl”不是“std”的成员</p>
- 手册文本表明字符集可以是“iconv”例程支持的任何编码,因此我猜测编译错误可能是由我的 iconv 库引起的。然后我测试了iconv:
iconv --from-code=UTF-16BE --to-code=UTF-8 --output=main_utf8.cpp main.cpp
按预期生成“main_utf8.cpp”文件。然后我尝试编译它:
g++ -finput-charset=UTF-8 main_utf8.cpp
请注意,我明确指定了输入字符集以查看我是否做错了什么,但这次生成了“a.out”而没有任何错误。当我运行它时,它可以产生正确的输出。
最后...
我不知道我哪里做错了。我在网上搜索试图找出这个编译器选项的一些例子,但我找不到。
请指教!谢谢!
进一步编辑:
多谢你们!您的回复很快!一些更新:
- 当我说“UTF-16”时,我的意思是“UTF-16 + BOM”。事实上,我使用的是 UTF-16BE。我已经更新了上面的文字。
- 一些答案说错误是由非 UTF-16 头文件引起的。如果是这种情况,以下是我的想法:在编写 C/C++ 项目时,我们总是会包含一些标准头文件,对吧?例如 stdio.h 或 iostream。如果 G++ 编译器只处理我们创建的源文件的编码,而不处理标准库中的源文件,那么这个 -finput-charset 选项的存在是为了什么?
最终编辑:
最后,我的解决方案是这样的:
- 一开始,我把我的源文件的编码改成了GB2312,正如下面“李斯特先生”所说。用了一阵子还行,后来发现不适合我的情况,因为系统中的其他部分大部分还是用UTF-8进行通信和接口的,所以很多地方都得转换编码……不仅我的工作开销,它也可能导致我的程序的一些性能下降。
- 后来我尝试将所有源文件转换为 UTF-8 + BOM。这样,Windows 中的 Visual Studio 可以愉快地编译它们,但 Linux 中的 GCC 会报错。然后我写了一个 shell 脚本来删除 BOM,在我想用 GCC 编译我的代码之前,我先运行这个脚本。
- 幸运的是,我不必在 Linux 中手动构建代码,因为我的项目中使用了持续集成工具 TeamCity 来自动生成构建。我可以更改 TeamCity 中的构建步骤,以帮助我在每日构建开始之前运行此脚本。
- 使用这种 UTF-8 + BOM + 脚本方法,我决定不在 Linux 中编辑我的源代码,因为如果我想这样做,我必须确保我的代码在提交之前可以成功构建,这意味着我必须运行在我构建代码之前删除 BOM 的脚本,这意味着 SVN 会报告每个文件都被修改(BOM 被删除),因此很容易错误地提交错误的文件。为了解决这个问题,我编写了另一个 shell 脚本来将 BOM 添加回源文件。虽然我仍然不会经常在 Linux 中编辑我的代码,但是当我真的需要时,我不必面对提交对话框中非常长的更改列表。