使用正确显示的名称创建c ++编码文件

时间:2012-10-06 12:36:08

标签: c++ windows linux encoding

我想要的只是创建一个文件,但在Linux和Windows上显示正确的名称。

在Linux上,这段代码工作正常,我认为这是因为正确处理UTF-8。

在Windows上存在一些问题。我有两种语言英语和俄语。如果我在我的编程环境(QT Creator)中使用系统编码,那么创建的文件几乎没有正确的名称,但是后悔来自德语的其他字母,法语(我怀疑日本,中文也不例外)不能在名称中使用文件,否则,因为可以看到它们被截断。所以,这是一个糟糕的方法。因为名字可以来自任何不同的语言。

即。我希望看到一个名字:
    string s="тдöüлотдFILE";

但它看起来如此:

enter image description here

我将Qt Creator中的编码更改为UTF-8,希望它能正常工作。

但现在我明白了:

string s="тдöüлотдFILE"; - expected name

得名: enter image description here 它看起来更糟糕。

我尝试将Qt Creator中的编码更改为UTF-16(我听说Windows使用它),但结果编译器拒绝在此编码中编译代码(与UTF16LE,BE,UTF32相同)

全局:

enter image description here

我怀疑问题在于Windows如何解释名称。但是我怎么能说它能够正确地显示它并且同时在Linux上工作呢?

2 个答案:

答案 0 :(得分:2)

嗯,这并没有描述如何解决它,但我“需要”超过500个字符: - )

在我尝试解释之前(以一种令人困惑的方式......)你正在看的问题是什么:你可能想尝试条件化平台的文件名(我不记得正式的宏来识别每个平台,所以请更换正确的):

#if defined(LINUX)
const char* Filename="тдöüлотдFILE";
#elif defined(WINDOWS)
const wchar_t* Filename=L"тдöüлотдFILE";
#endif

fstream f(Filename,...);

这仍然要求您的源代码采用编译器所期望的任何编码。如果这恰好是系统代码页,您甚至可能无法将这些字符转换为字符串文字(但是,如果wchar_t版本有效,您也可以使用字符的整数代码构造文件名。不太可读,但它不依赖于源文件编码。)

您正在处理的问题非常复杂,可能无法以简单的方式解决。

Windows在内部使用UTF16(因为XP,2000和NT使用UCS2,9x和3.x使用了代码页)。 Linux用户已经转向UTF-8,尽管仍有开发人员没有听说过。但它正在改善。

现在,虽然UTF-8具有代码页值,但它实际上不是系统代码页。代码页值仅适用于在代码页和UTF-16之间进行转换的函数,但每个系统仍然具有非UTF-8的遗留代码页。 Windows上的旧版或“ANSI”API采用在系统代码页中编码的字符串,而Unicode API采用UTF-16格式。没有其他选择。

显然,Windows程序喜欢使用UTF-16。但是,Linux根本不喜欢它,他们更喜欢UTF-8。我使用自己的框架来帮助在Windows,Linux和MacOS之间利用这些问题(当然还有其他事情);像Qt这样的现有框架也是这样做的。没有这些帮助,最安全的选择是坚持使用ASCII格式的字符串文字。

您的IDE设置只会影响源代码的存储方式;它不会影响运行时处理文字的方式,也不会影响运行时最终使用的API。

您可以尝试烹饪,例如使用微软“TCHAR”设置,这意味着允许使用“ANSI”编译程序(不,我有没有想法为什么他们选择那个名称)或带简单开关的Unicode。我对它并不特别熟悉或感兴趣,但它定义了类型(例如单个字符的TCHAR)和字符串文字的宏,并导致适用于Windows API函数的映射(比如调用'CreateFile'将会结果调用CreateFileW或CreateFileA)。想到的一个选项是将内容编译为Unicode的Windows,并为Linux定义适当的东西以生成基于“char”的代码变体。您可能还必须使用std :: basic_string而不是std :: string。

作为旁注,VisualC ++ 2012,据我所知,accepts source code采用UTF-8和UTF-16。但是,我不知道它在“char *”文字中的含义(在我的代码中,我只允许这些文字中的ASCII是安全的。'隐藏'字符来自字符串文件无论如何;我只需要文字为文件名,注册表项,内部密钥等。)。

答案 1 :(得分:0)

作为一般规则,将Unicode(非ascii)字符串编写为ansi字符串文字并不是一个好主意,因为此字符串使用一个字节字符,它们无法处理Unicode字符,然后您的编译器使用UTF- 8(这在大多数POSIX编译器中是默认的,因为UTF-8是OS的本机编码,但记住它取决于编译器而不是C ++标准)或使用系统的默认编码(在Windows中它可以在控制面板中配置,所以你的代码可能在一个系统上运行而在另一个系统中运行失败正确的方法是使用C ++宽字符串文字作为L"тдöüлотдFILE",在这种情况下,编译器将发出字符串的Unicode表示形式,该表示形式适用于具有所有设置的所有计算机。

现在问题是POSIX中的文件系统与UTF-8一起工作,而在Windows中使用UTF-16,如果使用boost是你的一个选项,你可以使用可爱的boost::path做所有事情对于你,否则你可以在Windows和POSIX上使用条件编译来实现它