0

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

在 Linux 上,这段代码运行良好,我认为这是因为正确处理了 UTF-8。

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

即我想要一个看起来像这样的名字:
string s="тдöüлотдFILE";

但它看起来是这样的:

在此处输入图像描述

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

但现在我明白了:

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

别名: 在此处输入图像描述 看起来更糟。

我试图将 Qt Creator 中的编码更改为 UTF-16(我听说 windows 使用它),但结果编译器拒绝以这种编码编译代码(UTF16LE、BE、UTF32 也是如此)

整体情况:

在此处输入图像描述

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

4

2 回答 2

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 的调用)。想到的一种选择是将内容编译为 Windows 的 Unicode,并为 Linux 键入定义/定义适当的内容以生成基于“char”的代码变体。您可能还必须使用 std::basic_string 而不是 std::string。

作为旁注,据我所知,VisualC++ 2012接受 UTF-8 和 UTF-16 的源代码。但是,我不知道它在“char *”文字中的内容(在我的代码中,我只允许此类文字中的 ASCII 是安全的。无论如何,“晦涩”字符都来自字符串文件;我只需要文字文件名、注册表项、内部密钥等)。

于 2012-10-06T15:26:22.477 回答
0

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

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

于 2012-10-06T15:29:06.070 回答