Lua:如何使 os.rename 和 os.remove 适用于包含 Unicode 字符的文件名?

如何使用仅标准 Lua 5.3 使 os.remove 和 os.rename 适用于包含 Unicode 字符的文件名?

filename = "C:\\τέστ.txt"
os.rename(filename, filename .. "1")

这并没有做任何事情。

我也尝试了这个但还是不起作用:

filename = "C:\\τέστ.txt"
t = {}
for p, c in utf8.codes(filename) do
  t[#t+1] = c
end
filename = "\\" .. table.concat(t, "\\")
os.rename(filename, filename .. "1")

有什么想法吗?非常感谢您的帮助!:)

点赞
用户9383219
用户9383219

我也曾尝试在未修改的 Lua 5.3(Windows 版本)中使用非 ASCII 文件名,但失败了。我认为需要一个修改过的 Lua 版本。 我的理解是,Lua 使用基本的 C 函数来处理文件名、命令和环境变量,但 Windows 使用 UTF-16 编码,并要求您使用宽字符串(在 Windows 上意味着 UTF-16)函数处理非 ASCII 文件名、命令和环境变量。

我编译并尝试使用过一种已修改的 Lua 版本,这个版本能很好地处理非 ASCII 文件名: lua-u8w。它使用处理文件等方面的宽字符串函数版本,并将 UTF-8 转换为 UTF-16,以便您可以在 Lua 中使用 UTF-8,而在处理 Windows 操作系统时则使用 UTF-16。

2019-01-10 00:26:02
用户1424244
用户1424244

在标准实现中,os.rename 调用 C 函数 rename,而 rename 会调用 Windows 的 CreateFileA 函数。此函数只能使用 ANSI 字符串,并对字符串执行内部从 ANSI 到 Unicode 的转换。

这使用了由您的本地设置指定的系统 ANSI 代码页。如果您的系统设置为希腊语,它可能会使用定义希腊字符的代码页 1253,但其他代码页的字符不可用。

我不确定,但如果系统代码页设置为 65001(UTF-8),则可以允许您使用 UTF-8。还有一个名为 AppLocale 的应用程序,可以仅为特定应用程序设置它。

如果可以使用外部库,似乎有一些库可以在系统 API 调用中使用宽字符。 这里 有一些例子。

2019-01-10 00:36:13
用户1442917
用户1442917

正如其他人所指出的,你不能使用 Lua 的原始版本做太多事情,因为它使用的是 CreateFileA 而不是这个函数的 Unicode 版本(CreateFileW)。如果你可以加载外部模块,你可以使用 winapi,因为它支持检索“短”文件名:

local ok, winapi = pcall(require, "winapi")
if ok then
  winapi.set_encoding(winapi.CP_UTF8)
  local shortpath = winapi.short_path(filepath)
  if shortpath ~= filepath then
    -- have the short path
  end
end

这段代码应该在所有平台上都可以工作(因为在不需要这种转换的 macOS 和 Linux 上无法加载 winapi)。如果短文件名不可用,则转换仍可能失败,并且可以使用 fsutil 8dot3name set DRIVE: 0 命令在 Windows 中进行配置(每个驱动器都可以)。

如果你将源文件名和目标文件名都通过转换(并删除可能由 short_file 调用创建的目标文件),重命名就会起作用。

2019-01-10 04:24:35