4

我在 Windows 中使用 Ruby 1.9.3 并尝试执行一个操作,我将文件名写入每行一个文件(我们将其称为文件列表),然后读取此文件列表,并调用 system() 运行另一个程序我将从文件列表中传递一个文件名。我用 system() 调用的那个程序将采用我传递给它的文件名并将其转换为二进制格式以在专有系统中使用。

在调用 system() 之前一切正常。我有一个 UTF-8 文件列表,从文件列表中读取文件名给了我正确的结果。但是当我跑步时

system("c:\foo.exe -arg #{bar}")

传递的 arg“bar”不是 UTF-8 格式。如果我使用日语、中文或任何文件名手动运行程序,它可以正常工作并正确编码文件,但如果我使用 system() 执行它就不会。我知道 bar 中的变量已正确存储,因为我在其他地方使用它没有问题。

我也试过:

system("c:\foo.exe -arg #{bar.encoding("UTF-8")}")
system("c:\foo.exe -arg #{bar.force_encoding("UTF-8")}")

也不工作。我只能假设这里的问题是将 unicode 传递给系统。

其他人可以确认系统是否确实支持或不支持这一点?

这是代码块:

  $fname.each do |file|
    flist.write("#{file}\n")  # This is written properly in UTF-8
    system("ia.exe -r \"#{file}\" -q xbfadd") # The file being passed here is not encoding right!
  end
4

3 回答 3

3

system()与大多数脚本语言中的函数一样,Ruby 的函数是 C 标准库system()调用的外层。MS C 运行时对所有面向字节的 C 标准库函数使用 Win32 ANSI API。

ANSI API 使用 Windows 系统语言环境(又名“ANSI 代码页”)在面向字节的字符串和用于文件名和 shell 命令的 Windows 原生 UTF16LE 字符串之间进行映射。不幸的是,无法将系统语言环境设置为 UTF-8;您可以在特定控制台上将代码页设置为 65001(Windows 相当于 UTF-8),但 MS CRT 在处理代码页 65001 时存在长期存在的错误,这会导致许多应用程序失败。

所以使用标准的跨平台、面向字节的 C 接口意味着你不能支持 Unicode 文件名或 shell 命令,这是相当可悲的。一些脚本语言通过显式调用 Win32 'W' (Unicode) API 而不是 C stdlib 接口来增加对 Unicode 文件名的支持。Ruby 1.9.x 在这方面正在取得进展,但system()还没有被关注。

您可以通过自己调用 Win32 API来修复它,例如CreateProcessW,但它并不是特别漂亮。

于 2012-08-03T08:13:16.807 回答
0

我赞成 bobince 的回答;我相信它是正确的。

我唯一要补充的是,一个额外的解决方法,这是一个 Windows 问题,是将命令行写入批处理文件,然后使用 system() 调用批处理文件。

我使用这种方法成功地解决了这个问题,同时运行 Calibre 的 ebook-convert 命令行工具来处理标题中包含 UTF-8/非英语字符的书。

于 2013-06-21T16:14:36.283 回答
0

我认为 bobince 的答案是正确的,对我有用的解决方案是:

system("c:\foo.exe -arg #{bar.encoding("ISO-8859-1")}")
于 2014-09-07T13:58:04.620 回答