【发布时间】:2016-03-24 09:02:28
【问题描述】:
我在使用 Perl 5.22 和 Postgresql (9.4) 的 Mac (10.11.2) 上遇到目录名称中包含 UTF8 字符的问题。 Postgresql 中的文本编码设置为 UTF8。
如果我有一个包含非 ascii UTF8 字符的目录名,如果目录名被 Perl 脚本读入或插入到 Perl 脚本中的字符串中,我可以 chdir() 到该目录。如果我将此名称插入 PG 表并将其读回(SELECT dirname FROM utfdirs),我无法 chdir 到该目录。但是,屏幕上打印的字符串是相同的,对两个字符串进行 Perl cmp 测试报告它们是相同的,guess_encoding() 报告两者都是 UTF8。
#!/opt/local/bin/perl5.22
use strict;
use Cwd;
use DBI;
use Encode;
use Encode qw/from_to/;
use Encode::Detect;
use Encode::Guess;
use Encode::UTF8Mac;
#
Encode::Guess->add_suspects(qw/utf-8-mac/);
#
my $dbname = 'test';
my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=localhost");
$dbh->do("SET client_min_messages TO WARNING");
#
my $homeDir = '/Users/jldasch';
chdir($homeDir) or die "Cannot cd to [$homeDir]\n";
opendir(D,".");
my @tdlist = sort grep(/(Lambda?)|(Delta?)/,readdir(D));
closedir(D);
$dbh->do("DELETE FROM utfdirs");
my $ins = $dbh->prepare("INSERT INTO utfdirs (dirname) VALUES (?)");
foreach my $d (@tdlist) {
chdir($homeDir);
my $ok = chdir($d) ? 1 : 0;
my $fp = "${homeDir}/${d}";
printf("%2d %s\n",$ok,$fp);
$ins->execute($fp);
}
my $rset = $dbh->selectall_arrayref("SELECT dirname FROM utfdirs ORDER BY dirname");
my $i = 0;
foreach my $r (@$rset) {
my $dbdir = $r->[0];
my $pdir = ${homeDir} . '/' . $tdlist[$i++];
print "$r->[0] $pdir\n";
my $encPerl = guess_encoding($pdir);
my $encDb = guess_encoding($dbdir);
print "Perl Encoding [$encPerl->{Name}]\n";
print "Db Encoding [$encDb->{Name}]\n";
unless ( chdir($dbdir) ) {
print "Cannot CD to DbDir [$dbdir]\n";
print "DbDir and PerlDir Match\n" if ($dbdir eq $pdir)
}
exit;
输出:
bash-3.2$ ./utfstuff2.pl
1 /Users/jldasch/DeltaΔ
1 /Users/jldasch/Lambdaλ
/Users/jldasch/DeltaΔ /Users/jldasch/DeltaΔ
Perl Encoding [utf8]
Db Encoding [utf8]
Cannot CD to DbDir [/Users/jldasch/DeltaΔ]
DbDir and PerlDir Match
/Users/jldasch/Lambdaλ /Users/jldasch/Lambdaλ
Perl Encoding [utf8]
Db Encoding [utf8]
Cannot CD to DbDir [/Users/jldasch/Lambdaλ]
DbDir and PerlDir Match
所以在我目前检查的级别上,Perl 告诉我字符串是相同的(cmp 和guess_encoding()),它们打印相同,但它们不一样。
如何将 Postgresql 返回的 UTF8 字符串转换为(在 Perl 中)被接受为 chdir() 的有效目录名的字符串?
【问题讨论】:
-
有一个模块 Encode::UTF8Mac 似乎可以解决这个问题。
my $macOkDir = Encode::decode('utf-8-mac',$dbDir) -
使用
Devel::Peek比较有编码问题的字符串。请使用Devel::Peek::Dump显示$dbdir和$pdir的输出 -
字符串是完全相同的字节吗?我想知道这里是否存在 precomposed-vs-decomposed-representation 问题。
标签: perl postgresql utf-8