【问题标题】:opening files on non-ANSI systems via old (non wchar) API functions通过旧的(非 wchar)API 函数在非 ANSI 系统上打开文件
【发布时间】:2011-06-14 23:07:19
【问题描述】:

我正在编写一些让我发疯的中间件。我正在寻找一些 I18N 专家来帮助我 - 这对我来说都是全新的。

目前这一切都在 Windows 中,但它也必须在 Linux 和 Mac 上运行,尽管我敢打赌这些会很容易。

我有一个系统(我无法触摸),它会为我提供一个 wchar_t* 形式的字符串。它接受 UTF-8 或当前语言环境的输入,并神奇地给我一个 wchar_t*。

我正在使用另一个 API,它只能将文件名作为 char*(我也无法触摸)。

所以我一直在做的是在 wchar_t* 中获取我的文件名并使用 Windows API 函数 WideCharToMultiByte 并将其转换为 char* 并将其传递给我的其他 API 函数。在 QA 决定使用日本操作系统之前,它工作得很好。现在 fopen(在我无法触及的 API 深处)失败了。

我已尝试在 WideCharToMultiByte 调用中同时使用 CP_ACP 和 CP_UTF8,即使文件名中包含日文字符,两者都可以在我的开发(美国英语)机器上工作。但两者都在日本操作系统上失败。

关于我应该如何处理这些文件名的任何提示?

【问题讨论】:

  • 能否记录下每一步返回的字符数据,对比一下美英OS和日文OS?给出不同结果的第一个调用可能表明是哪个 API 导致了问题。
  • 您能否尝试获取有关目标计算机上哪个区域设置处于活动状态的信息? setlocale(LC_CTYPE, ""); 的结果字符串已经很有趣了。

标签: c++ windows winapi unicode internationalization


【解决方案1】:

好吧,解决这个问题的正确方法是修复其他 API。只接受狭窄的非 unicode 文件名是一种破坏行为。

但是……你说过你不能那样做。您可以通过获取不包含任何非 ANSI 字符的短文件名并将其传递给损坏的 API 来解决此问题。 (原因是短文件名是为 16 位应用程序设计的,而 16 位窗口根本不支持 Unicode)

当然,如果文件名不能表示为短文件名,或者目标机器上关闭了短文件名,这将失败——但它确实是这里唯一的选择。

编辑:还有一点需要注意——如果文件名包含 Unicode,那么短文件名通常是不可读的。它将被重命名为使用一堆十六进制垃圾,这些垃圾在限制为 8.3 文件名的世界中唯一标识文件。

【讨论】:

  • 你是说标准 C++ 库“简直坏了”?
  • @dan04:C++ 标准库为所有内容定义了宽字符和窄字符 API。 (在 C++0x 中,对 Unicode 转换格式的支持更加明确)因此,不,不是。大部分都坏了,是的,但整个图书馆都没有。不过,C 和 C++ 在这里真的不能过分指责,因为它们比 Unicode 早了大约 15 年。
  • 不,它没有。 Windows 为所有内容定义了宽字符和窄字符 API。但是标准 C 缺少像 _wfopen_wstat 这样的函数。
  • @dan:C++ Unicode 方面的大部分问题都已在 C++0x 中修复,并且有人提议修复 C1X 中的 C 问题,但两种语言在使用 Unicode 时确实存在严重问题. (C 在这里更可以原谅,因为它的第一个标准比 Unicode 早了 4 年,C++ 没有什么借口,因为它是第一个标准比 Unicode 晚了大约 5 年......)
  • 是的,我尝试了各种技巧,但使用短文件名是唯一可行的方法。呸!我讨厌 Windows。 Mac 和 Linux 很简单——它们只使用 UTF-8。
猜你喜欢
  • 2014-06-26
  • 2015-11-25
  • 2010-10-05
  • 2018-04-10
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 2014-12-30
相关资源
最近更新 更多