我正在德语Windows 7下运行最新的perl,我想在我的perl程序中的任何地方使用utf8(用于脚本,文件内容,文件名,邮件文本等)。
一切正常,但是在尝试处理文件名中包含特殊字符的文件时遇到了问题。甚至system
调用也不起作用。因此,(如何)我可以告诉perl在任何地方使用utf8
?
我用encode
和decode
尝试了一段时间,但目前尚不清楚为什么它能正常工作...另外,我还需要encode('cp850', TEXT)
才能在命令提示符窗口中正确显示
示例:
当我需要复制文件时,仅当我使用File::copy(encode("iso-8859-1", $filename), ...)
且要使用pdf文件时,它才有效,命令是system(encode('cp850', sprintf('pdftk.exe %s...', decode('utf8', $file))));
为什么会这样(尤其是系统调用中的解码),还有更简单的方法吗?也许与use open ':encoding...'
有所关联,但到目前为止我还没有运气。
答案 0 :(得分:3)
这是最近刚遇到这个确切问题的人的真实,具体和明确的答案:
在Windows上,不能让Perl 5.28.0或更低版本对所有内容使用UTF8。
这是为什么:从Perl 5.28.0开始,为此,perl核心文件处理功能被致命地搞砸了。 Windows将文件名存储为(简单地说)UTF16,并且Windows api宽字符函数将文件名返回为宽字符,类似于Perl内部已使用的字符。但是,当从文件系统中获取这些文件时,perl核心将它们转换为本地系统编码中的字节。反之亦然。因此,从道德上讲,您具有这样的流程,解释为Perl:
use utf8;
sub readdir_perl {
my $dir = shift;
my $fn = readdir $dir;
$fn = encode $fn, CP_ACP;
return $fn;
}
sub open_perl {
my $fn = shift;
$fn = decode $fn, CP_ACP;
open my $FH, $fn;
return $FH;
}
两个重要说明:
?
字符,从而给您带来少量的垃圾。也就是说,你能做什么?
system
,但要确保将所有内容都视为字节并适当地解码/编码。存在一些example code。您还需要手动实现ALL文件处理,并且无法有用地修补其他代码来使用LongPath函数。答案 1 :(得分:1)
首先将命令提示符的代码页设置为65001
chcp 65001
这将允许您在命令提示符下使用和显示utf8字符。 文件名取决于所使用的文件系统。 NTFS使用UTF-16LE编码存储文件名。有关如何在Windows上使用Unicode文件名创建和访问文件的问题,请参见this问题。
System()命令需要在与命令提示符相同的代码页中进行编码,因此在执行chcp 65001
之后,您可以在utf8中对system()
命令进行编码
答案 2 :(得分:0)
由于目前没有合适的答案,我将尝试在此处写下一个工作示例。希望有一次它不会再有错误了。在此之前,请发布您的建议/解决方案,一旦成功,我将对其进行测试和更新。
当前未解决的问题:
open
打开pdf文件CAM::PDF->new
打开pdf文件system
调用处理pdf文件test.pl:
$| = 1;
use strict;
use warnings;
use utf8;
use CAM::PDF;
use open ':std', ':encoding(UTF-8)';
BEGIN {
if ($^O eq "MSWin32") {
require Win32::Unicode::File;
Win32::Unicode::File->import();
}
}
my $file = 'Täst.pdf';
print "FILENAME: $file\n";
unlink("file2.pdf");
copyW($file, "file2.pdf") or print "cannot copy file: $!\n";
if (!open(FH, $file)) {
print "cannot open file by open '$file': $!\n";
}
else {close FH}
my $pdf = CAM::PDF->new($file) or print "cannot open file by CAM::PDF: $!\n";
print "\n";
system("pdftk.exe $file cat 2 4 output out.pdf") or print "cannot run command: $!\n";
print "\n";
test.cmd:
要求为命令行窗口设置字体“ Lucida Console”。
@echo off
chcp 65001 >nul
call perl.exe test.pl
chcp 850 >nul
pause
Windows下的输出:
FILENAME: Täst.pdf
cannot open file by open 'Täst.pdf': No such file or directory
cannot open file by CAM::PDF: No such file or directory
Error: Unable to find file.
Error: Failed to open PDF file:
Täst.pdf
Drücken Sie eine beliebige Taste . . .