perl - 在 Windows 上的 Perl 中处理 unicode 目录和文件名

标签 perl encoding directory tk-toolkit

我在使用 Perl 和 Windows 时遇到编码问题。在运行 Perl(草莓 5.16)和简单的 TK GUI 的 Windows 7 上,我需要打开文件和/或访问名称/路径中包含非英语字符的目录。为了打开文件,我提出了这个似乎工作正常的解决方案:

#!/usr/bin/perl -w

use strict;
use warnings;
use Win32::Unicode::File;
use Encode;
use Tk;

my $mw = Tk::MainWindow->new;
my $tissue_but = $mw->Button(
    -text => 'Open file',
    -command =>  [ \&select_unicode_file ],
);
$tissue_but->grid( -row => 3, -column => 1 );
Tk::MainLoop();

sub select_unicode_file{
my $types = [ ['Txt', '.txt'],
          ['All Files',   '*'],];
my $input_file= $mw->getOpenFile(-filetypes => $types);
my $fh = Win32::Unicode::File->new;
if ($fh->open('<', $input_file)){
  while (my $line = $fh->readline()){
    print "\n$line\n";
  }
   close $fh;
}
 else{
  print "Couldn't open file: $!\n";
}
}

这将正确打开诸如 Поиск/Поиск.txt 之类的文件

我不能做的是简单地获取目录路径并处理它。我想我应该使用 use Win32::Unicode::Dir 但我真的无法理解文档。

应该是这样的:

#!/usr/bin/perl -w

use strict;
use warnings;
use Win32::Unicode::Dir;
use Encode;
use Tk;

my $mw = Tk::MainWindow->new;
my $tissue_but = $mw->Button(
    -text => 'Open file',
    -command =>  [ \&select_unicode_directory ],
);
$tissue_but->grid( -row => 3, -column => 1 );
Tk::MainLoop();

sub select_unicode_directory{
my $dir = $mw->chooseDirectory( );
my $wdir = Win32::Unicode::Dir->new;
my $dir = $wdir->open($dir) || die $wdir->error;
my $dir_complete = "$dir/a.txt";
open (MYFILE, $dir_complete );
    while (<MYFILE>) {
    chomp;
    print "$_\n";
}
close (MYFILE); 
}

最佳答案

存在逻辑错误:

my $dir = $wdir->open($dir) || die $wdir->error;
my $dir_complete = "$dir/a.txt";

$wdir->open('path') 返回一个对象,而不是字符串。你不能像路径一样使用它。但这还不是最糟糕的。遗憾的是,Tk 实现似乎还不支持 Unicode 文件名(包括 ChooseDirectory)。我想您必须编写一个自定义目录选择器,但我不确定它是否可能。

它能够列出 ascii-chars 文件夹中的文件(并且 ->fetch 可以列出 utf-8 文件),并且在打开包含 utf-8 字符的文件夹时崩溃。好吧,公平地说,打开 ?????? 时它会崩溃。

use strict;
use warnings;
use Win32::Unicode::Dir;
use Win32::Unicode::Console;
use Encode;
use Tk;

my $mw = Tk::MainWindow->new;
my $tissue_but = $mw->Button(
    -text => 'Select dir',
    -command =>  [ \&select_unicode_directory ],
);
$tissue_but->grid( -row => 3, -column => 1 );
Tk::MainLoop();

sub select_unicode_directory {
    my $wdir = Win32::Unicode::Dir->new;
    my $selected = $mw->chooseDirectory(-parent =>$mw);
       # http://search.cpan.org/dist/Tk/pod/chooseDirectory.pod#CAVEATS
       $selected = encode("utf-8", $selected);
    print "selected: $selected\n";

    $wdir->open($selected) || die $wdir->error;

    print "\$mw->chooseDirectory:    $selected\n";
    print "\$wdir->open(\$selected): $wdir\n";


# CRASH HERE, presumably because winders can't handle '?' in a file (dir) name
    for ($wdir->fetch) {
# http://search.cpan.org/~xaicron/Win32-Unicode-0.38/lib/Win32/Unicode/Dir.pm
        next if /^\.{1,2}$/;
        my $path = "$selected/$_";
        if (file_type('f', $path)) { print "file: $path\n"; } 
        elsif (file_type('d', $path)) { print " dir: $path\n"; }
    }
    print "closing \n";
    $wdir->close || die $wdir->error;

}

示例(开头 Поиск/):

下面的两个示例均使用:为 MSWin32-x64-多线程构建的 Strawberry Perl 5.12.3 运行

selected: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/?????
$mw->chooseDirectory:    C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/?????
$wdir->open($selected): Win32::Unicode::Dir=HASH(0x2e38158)
>>> perl crash <<<

样本输出(Поиск的开放父级):

selected: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk
$mw->chooseDirectory:    C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk
$wdir->open($selected): Win32::Unicode::Dir=HASH(0x2b92c10)
file: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/.select_uni_dir.pl.swp
file: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/o
file: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/o.dir
file: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/select_uni_dir.pl
file: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/select_uni_file.pl
 dir: C:/cygwin/home/jaroslav/tmp/so/perl/open-file-tk/Поиск

结论

Tk 目录选择器返回 ??????而不是 Поиск。在寻找在 Tk 中启用 Unicode 的方法时,我发现了这一点:

http://search.cpan.org/dist/Tk/pod/UserGuide.pod#Perl/Tk_and_Unicode :

(...) Unfortunately, there are still places in Perl ignorant of Unicode. One of these places are filenames. Consequently, the file selectors in Perl/Tk do not handle encoding of filenames properly. Currently they suppose that filenames are in iso-8859-1 encoding, at least on Unix systems. As soon as Perl has a concept of filename encodings, then Perl/Tk will also implement such schemes.

所以乍一看,你想要做的事情似乎是不可能的(除非你 编写或查找自定义目录选择器)。事实上,这可能不是一个坏主意 提交此错误,因为 GUI 确实显示“Поиск”,因此错误出现在返回值中。

关于perl - 在 Windows 上的 Perl 中处理 unicode 目录和文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17369977/

相关文章:

perl - 以Perl格式书写时如何使用Unicode字符?

perl - 在 perl 中解析 yaml --> 代码 : YAML_LOAD_ERR_BAD_MAP_ELEMENT

javascript - 将 JSON(jQuery) 发送到 PHP 并对其进行解码

perl - 使用 perl 打开文件并替换单词

perl - 如何从 perl 中的文本中提取引用的部分?

iOS 编码 ISO-8859-9

css - 如何基于base64编码css中的图片路径?

bash - 按日期将文件分类到子文件夹中 - bash

r - 在函数内创建文件夹

c# - 如何按日期范围从文件夹中获取所有目录?