2010-11-20 152 views
3

我正在努力处理包含非英文字符(Activestate Perl,Windows XP)的路径。如何打开,写入,复制位于路径中的文件,并说出希腊语/俄语/法语重音字符?比方说,我想复制我的text.txt文件的目录是:C:\Documents and Settings\στα\DesktopPerl:在Windows上管理路径编码

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."; 
+1

你的代码片段有一个问题:你想要“\\ text.txt”而不是“\ text.txt”。这可能不是你最后的问题。 – Leolo 2010-11-21 06:08:30

回答

0

Perl的原生功能无法在这种情况下使用。使用支持Unicode字符的Win32模块中的函数。 Win32首次与perl v5.8.7发布。

+0

谢谢你的建议。除非(Win32 :: CopyFile($ input,$ ansi_path,1))我改变脚本为 if($ err == ERROR_ALREADY_EXISTS){ 警告“目录存在,没有问题\ n”; } else { die Win32 :: FormatMessage($^E); } }但它不适用于希腊!任何想法? – Richard 2010-11-20 12:00:37

+0

对不起。目前我没有Windows系统进行测试。如果我能够测试,我会更新我的答案。 – 2010-11-20 15:06:46

+0

艾伦的答案是正确的,但不正确。您*可以*使用Perl的本地函数和宽字符编码,但是在将文件名交给Perl之前,您必须将文件名编码为系统编码。看到我的答案。 – 2010-12-19 06:13:34

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

我没有权限投票了从克里斯·多兰的答案,但我有在日本使用基于Win32::Codepage的相同解决方案解决了路径名称的问题。

这可能需要确认,但我认为Perl对所有非A​​SCII路径名都采用UTF8。在Linux和OS X上,这可以正常工作,因为操作系统路径名以UTF8编码。但是,在较早版本的Windows(Windows 7之前版本)中,路径名是在该国的语言环境中编码的(例如,日本的Shift-jis)。所以,返回非ASCII字符路径名的所有Perl调用都会搞砸。

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

+1

你在上面的答案中有一点不正确。 Perl默认使用8位Latin-1编码字符串。像Shift-JIS一样,Latin-1是ASCII的超集。 – 2010-12-23 15:27:18

+0

您的投票给了我评论权限。谢谢! – Lozzer 2010-12-27 11:09:19

+0

对不起,以上错误。是的,它是拉丁语1.主要的一点是Perl使用UTF8,它在Windows系统上混淆了路径名。我仍然感到惊奇的是,你不能在Perl中使用简单的“打开”命令(在非拉丁语的Windows系统上)而不会搞乱Win32 :: Codepage。 – Lozzer 2010-12-27 11:15:42

0

我发现我必须在Microsoft Windows Vista上禁用UAC(User Access Control)才能成功安装Win32::LocaleWin32::Codepage。 (谢谢克里斯多兰,编写后一个模块。)

0

我在Windows 7和更新版本上也遇到了UAC(用户访问控制)问题。 我终于发现,自从Windows Vista以来,对所需注册表项的访问只具有读权限。 您可以轻松地修补的Win32 ::代码页没有管理权限的工作,如果你在你最喜欢的编辑器中打开该文件并替换:

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

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

这对我的帮助安装。

+1

这与文件路径中的重音字符有什么关系? – 2015-11-26 00:25:52