Perl:管理Windows上的路径编码

时间:2010-11-20 11:10:37

标签: windows perl encoding

我正在努力使用包含非英文字符的路径(Activestate Perl,Windows XP)。如何打开,写入,复制等位于路径中的文件,并说出希腊语/俄语/法语重音字符?假设我想将text.txt文件复制到的目录是:C:\Documents and Settings\στα\Desktop

use File::Spec;
my $save = File::Spec->canonpath( $mw->chooseDirectory() );

my $file = catfile($save , "renamed_text.txt");

my $input = "üüü\text.txt";
copy ($input, $file) or die "File cannot be copied.";

5 个答案:

答案 0 :(得分:3)

我没有权利对Chris Dolan的答案进行投票,但我已经在日本使用基于Win32::Codepage的相同解决方案为路径名解决了这个问题。

这可能需要确认,但我认为Perl假定所有非ASCII路径名都使用UTF8。在Linux和OS X上,这很好用,因为操作系统路径名是以UTF8编码的。但是,在较旧版本的Windows(Windows 7之前版本?)中,路径名是在该国家/地区的区域设置中编码的(例如,日本的Shift-jis)。因此,所有返回带有非ASCII字符的路径名的Perl调用都会搞砸。

我使用的解决方案是使用Win32:Codepage查找语言环境编码,然后在读取文件时将其编码为UTF8。然后,在编写(或更新)文件时,我会解码回语言环境编码。

答案 1 :(得分:2)

几年前我在一个项目中遇到了同样的问题(我们的PAR打包GUI应用程序必须在Shift-JIS编码下工作)。我尝试了很多技巧让Perl 5.8自动完成。最后,我的繁琐但有效的解决方案是在将每个文件名传递给内置函数之前对其进行编码。

首先,设置效用函数:

use Encode;
use Win32::Codepage;
my $encoding = Win32::Codepage::get_encoding() || q{};
if ($encoding) {
    $encoding = Encode::resolve_alias($encoding) || q{};
}
sub encode_filename {
    my ($filename) = @_;
    return $encoding ? encode($encoding, $filename) : $filename;
}

然后,在任何地方使用

next if (! -d encode_filename($tmpldir));
my $file = SWF::File->new(encode_filename($dest));
@entries = File::Slurp::read_dir(encode_filename($srcdir));
etc...

我甚至写了一个小检查器,以确保我到处使用它!

egrep "\-[a-zA-Z] |open[^_]|[^ ]parse|unlink|symlink|mkdir[^_]|mkpath|rename[^\']|File::Copy::copy|rmtree|getTemplate[^D]|write_file|read_file|read_dir" *.pl `find lib -name '*.pm'` | grep -
v encode_filename | egrep -v '^[^:]+: *(\#|_announce|debug)'

如果你错过了一个,你将在运行时收到“宽字符”警告..​​....

答案 2 :(得分:0)

在这种情况下不能使用Perl的本机函数。使用Win32模块中支持Unicode字符的函数。 Win32首次使用perl v5.8.7发布。

答案 3 :(得分:0)

我发现在成功安装Win32::LocaleWin32::Codepage之前,我必须在Microsoft Windows Vista上禁用UAC(User Access Control)。 (谢谢Chris Dolan编写后一个模块。)

答案 4 :(得分:0)

我在Windows 7及更高版本上也遇到过UAC(用户访问控制)问题。 我终于发现,从WIndows Vista开始,访问所需的注册表项只具有读取权限。 如果在您喜欢的编辑器中打开文件并替换,您可以轻松地将Win32 :: Codepage修补为无需管理员权限的工作:

  $codekey = Win32::TieRegistry->new($CODEPAGE_REGISTRY_KEY,
                                     { Delimiter => "/" }
                                    );

  $codekey = Win32::TieRegistry->new($CODEPAGE_REGISTRY_KEY,
                                     { Access=>"KEY_READ", Delimiter => "/" }
                                    );

这对我的安装有所帮助。