代码之家  ›  专栏  ›  技术社区  ›  Sol

Windows代码页与标准C/C++文件名的交互?

  •  5
  • Sol  · 技术社区  · 16 年前

    一位客户抱怨说,我们的代码曾经在文件名中使用日文字符来编写文件,但现在它不再适用于所有情况。我们总是用很好的旧char*字符串来表示文件名,所以它曾经起过作用,这让我有点震惊,而且我们还没有做任何我认为应该让它停止工作的事情。我让他们给我发了一个文件,里面有一个嵌入的文件名,从我们的软件中导出,看起来字符串使用十六进制字符82和83作为双字节序列的第一个字符来表示日语字符。在网上闲逛让我相信这可能是SHIFT_JIS和/或Windows代码页932。

    在短期内,我希望有人能对特定的Windows fopen与ofstream::open issue给我一些启示。我真的想知道Unicode的开场白吗C++中的文件名,在Windows、Linux和OS X上。

    更新:我向客户发送了一个小测试程序。它已经验证了fopen可以很好地使用SHIFT_-JIS文件名,而std::ofstream不能。这是在visualstudio2005中进行的,无论我使用的是默认的语言环境还是“C”语言环境,都会发生这种情况。

    6 回复  |  直到 16 年前
        1
  •  3
  •   Mihai Nita    16 年前

    fopen或ofstream::open之类的函数将文件名作为char*,但这会被解释为在系统代码页中。

    更改系统代码页,应用程序“停止工作” 我怀疑这就是这里所发生的事情(自win2000以来,Windows在这个领域没有大的变化)。

    http://www.mihai-nita.net/article.php?artID=20050611a

    从长远来看,您可能会考虑改用Unicode(并使用wopen,wofstream)。

        2
  •  2
  •   Tometzky    16 年前

    • 对于C: glib
    • glibmm 还使用UTF-8中的文件名,需要glib;
    • 对于C++: boost 可以对文件名使用wstring。

    我很确定.NET/mono框架也包含可移植的文件系统函数,但我不知道它们。

        3
  •  0
  •   rmeador    16 年前

    我几乎可以肯定,在Linux上,文件名字符串是一个UTF-8字符串(例如,在EXT3文件系统中,唯一不允许的字符是斜杠和NULL),存储在一个普通的 char * . 手册页似乎没有提到字符编码,这使我相信它是UTF-8的系统标准。OSX可能使用相同的方法,因为它来自相似的根,但我对此不太确定。

        4
  •  0
  •   Stefan    16 年前
        5
  •  0
  •   mouviciel    16 年前

    macosx使用Unicode作为本机字符编码。基本的字符串对象是CFString和NSString。它们将字符数组存储为Unicode。

        6
  •  0
  •   Pjacobi    12 年前

    有人还在看这个吗?我刚刚研究了这个问题,没有找到任何答案,所以我可以在这里解释我的发现。

    在VS2005中,fstream文件名处理非常奇怪:它不使用系统默认编码,即使用GetACP获得的并在控制面板/区域和语言/管理中设置的编码。但总是CP 1252——我相信。

    这可能会引起很大的混乱,微软已经在以后的VS版本中消除了这种怪癖。

    VS2005的所有解决方法都有其缺点:

    1. 在任何地方使用Unicode转换代码

    2. 不要使用窄字符文件名打开fstream,始终使用系统默认编码(使用宽字符文件名open/ctor)将其转换为Unicode

    3. 使用GetACP()检索代码页,然后执行

    setlocale (LC_ALL, ("." + lexical_cast<string> (GetACP())).c_str())