9

Perl と Windows でエンコーディングの問題があります。Perl (strawberry 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); 
}
4

1 に答える 1

1

次の場所に論理エラーがあります。

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-multi-thread 用にビルドされた 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 dir セレクターは ????? を返します。Поискの代わりに。TkでUnicodeを有効にする方法を探しているときに、これを見つけました:

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

(...) 残念ながら、Unicode を知らない Perl の場所がまだあります。これらの場所の 1 つはファイル名です。その結果、Perl/Tk のファイル セレクターは、ファイル名のエンコードを適切に処理しません。現在、少なくとも Unix システムでは、ファイル名は iso-8859-1 エンコーディングであると想定しています。Perl がファイル名エンコーディングの概念を持つとすぐに、Perl/Tk もそのようなスキームを実装します。

したがって、一見すると、あなたがやろうとしていることは不可能に思えます (カスタム dir-selector を作成または見つけない限り)。実際、このバグを送信するのは悪い考えではないかもしれません。なぜなら、GUI に"Поиск" が表示されたため、エラーは戻り値にあるからです。

于 2013-07-29T15:29:26.273 に答える