如何使用Perl在Windows上创建一个Unicode目录?

5

我在创建包含Unicode的目录名称时遇到了困难。我的操作系统是Windows XP,使用的是Perl Camelbox 5.10.0。

迄今为止,我一直使用use File::Path qw(make_path)来创建目录-这在出现第一个西里尔字母目录之前运行良好。

对于文件,如果文件名采用UTF-16LE编码,则Win32API::File qw(CreateFileW)可以正常工作。是否有类似于目录的东西?或者可以通过参数告诉CreateFileW在不存在时创建Unicode路径吗?

谢谢,
Nele


请参见 https://dev59.com/UnI-5IYBdhLWcg3wsKv9 - Sinan Ünür
@Sinan:如果我理解正确的话,你下面的例子是你在之前提到的那个线程中所给出的回答的一小部分。当这个问题在11月份出现在SO上时,我简要地阅读了一下这个线程,但是我没有记住它。谢谢! - Nele Kosog
2个回答

6

Win32.pm 提供了一个接口给 CreateDirectory 等函数使用:

Win32::CreateDirectory(DIRECTORY)

创建 DIRECTORY 目录,成功时返回 true。失败时请检查 $^E 获取详细错误信息。

DIRECTORY 可包含系统代码页之外的 Unicode 字符。目录创建完成后,您可以使用 Win32::GetANSIPathName() 获取可传递给系统调用和外部程序的名称。

之前的答案:

注意:这里记录下来是因为您试图在程序中直接使用 CreateDirectoryW

如果要手动执行此操作,请使用 Win32::API 导入 CreateDirectoryW

Win32::API->Import(
    Kernel32 => qq{BOOL CreateDirectoryW(LPWSTR lpPathNameW, VOID *p)}
);

您需要对$path进行编码,以便用于CreateDirectoryW函数:

#!/usr/bin/perl

use strict; use warnings;
use utf8;

use Encode qw( encode );
use Win32::API;

Win32::API->Import(
    Kernel32 => qq{BOOL CreateDirectoryW(LPWSTR lpPathNameW, VOID *p)}
);

binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';

my $dir_name = 'Волгогра́д';

my $ucs_path = encode('UCS-2le', "$dir_name\0");
CreateDirectoryW($ucs_path, undef)
    or die "Failed to create directory: '$dir_name': $^E";
E:\> dir
2010/02/02  01:05 PM              Volgograd
2010/02/02  01:04 PM              Moscow
以上是一个命令行窗口展示的目录内容,其中包含两个文件夹名称,分别为Volgograd和Moscow。

谢谢。我会使用Win32::CreateDirectory。我对Unicode世界还很陌生,觉得它相当复杂 - 或许这只在使用Perl的Windows上是真的 - 我不确定。 - Nele Kosog
Win32::GetANSIPathName() 返回的名称似乎无法与外部命令配合使用。它是否需要转换为系统代码页或其他什么东西? - Freon Sandoz

0

更新一下这个问题,以适应2018年。

令人难以置信的是,ActivePerl 5.24 仍然不支持简单地传递Unicode路径到open()/mkdir(),以及扩展到File::Path::mkpath(),因为底层的Perl代码仍然调用20世纪ASCII版本的Windows CreateFile()。 疯狂!这怎么可能不比在过去10年中进行的众多晦涩的Perl更改更高优先级?!

即使你使用了'use utf8;'或其他无数咒语,这也是真实的。

因此,即使在今天,我们仍然需要为Windows编写特殊情况的代码,以执行此最基本的功能(创建/访问Unicode文件名)。

幸运的是,Win32::Unicode模块有一个很好、易于使用的Win32::Unicode::Dir::mkpathW()函数,它可以完全满足您的需求,并适用于Unicode(以及出色的copyW()moveW()函数)。

很遗憾,自从Perl 5.16以来,这个模块没有通过安装测试,ActiveState也将其从方便的ppm存储库中删除了(https://code.activestate.com/ppm/Win32-Unicode/)。

幸运的是,有一种方法可以让它工作,因为失败的3个测试(与“print”相关)不用于文件/目录创建:

步骤1:ppm install dmake

步骤2:ppm install MinGW

步骤3:perl -MCPAN -e shell然后force install Win32::Unicode

即使您已经在计算机上安装了Microsoft Visual Studio,步骤1和2也是必需的;显然,现在使用MinGW构建Perl,模块也必须如此。

呼。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接