2011-09-25 76 views
4

我在这个路径名中如何获得这样一种奇怪的编码?
在我的文件管理器(Dolphin)中,路径名看起来不错。关于路径名编码的问题

#!/usr/local/bin/perl 
use warnings; 
use 5.014; 
use utf8; 
use open qw(:encoding(UTF-8) :std); 
use File::Find; 
use Devel::Peek; 
use Encode qw(decode); 

my $string; 
find(sub { $string = $File::Find::name }, 'Delibes, Léo'); 
$string =~ s|Delibes,\ ||; 
$string =~ s|\..*\z||; 
my ($s1, $s2) = split m|/|, $string, 2; 

say Dump $s1; 
say Dump $s2; 

# SV = PV(0x824b50) at 0x9346d8 
# REFCNT = 1 
# FLAGS = (PADMY,POK,pPOK,UTF8) 
# PV = 0x93da30 "L\303\251o"\0 [UTF8 "L\x{e9}o"] 
# CUR = 4 
# LEN = 16 

# SV = PV(0x7a7150) at 0x934c30 
# REFCNT = 1 
# FLAGS = (PADMY,POK,pPOK,UTF8) 
# PV = 0x7781e0 "Lakm\303\203\302\251"\0 [UTF8 "Lakm\x{c3}\x{a9}"] 
# CUR = 8 
# LEN = 16 

say $s1; 
say $s2; 

# Léo 
# Lakmé 

$s1 = decode('utf-8', $s1); 
$s2 = decode('utf-8', $s2); 

say $s1; 
say $s2; 

# L�o 
# Lakmé 

回答

13

不幸的是你的操作系统的路径API是另一种“二进制接口”,你将不得不使用Encode::encodeEncode::decode得到预期的结果。

大多数操作系统将路径名视为八位字节序列(即字节)。该序列是否应该被解释为拉丁文-1,UTF-8或其他字符编码是应用程序的决定。因此,readdir()返回的值只是一串八位组,并且File::Find不知道您希望路径名为Unicode码点。它形成$File::Find::name通过简单地连接目录路径(你提供的)和你的操作系统通过readdir()返回的值,这就是你如何得到八位位组的代码点。

经验法则:每当将路径名传递给操作系统,Encode::encode()它确保它是一个八位字节序列。当从OS获得一个路径名,Encode::decode()它的字符集,你的应用程序需要它

您可以通过调用find这种方式让你的工作方案:

find(sub { ... }, Encode::encode('utf8', 'Delibes, Léo')); 

,然后调用Encode::decode()时使用的$File::Find::name值:

my $path = Encode::decode('utf8', $File::Find::name); 

更清楚,这是多么$File::Find::name形成:

use Encode; 

# This is a way to get $dir to be represented as a UTF-8 string 

my $dir = 'L' .chr(233).'o'.chr(256); 
chop $dir; 

say "dir: ", d($dir); # length = 3 

# This is what readdir() is returning: 

my $leaf = encode('utf8', 'Lakem' . chr(233)); 

say "leaf: ", d($leaf); # length = 7 

$File::Find::name = $dir . '/' . $leaf; 

say "File::Find::name: ", d($File::Find::name); 

sub d { 
    join(' ', map { sprintf("%02X", ord($_)) } split('', $_[0])) 
} 
+0

像文件测试运算符一样使用解码或编码文件名称的'-f'? –

+1

文件测试运算符也需要八位字节 – moritz

-2

POSIX文件系统API被破坏,因为没有编码被强制执行。期。

可能发生许多问题。例如,路径名甚至可以包含latin1和UTF-8,具体取决于路径上的各种文件系统如何处理编码(以及它们是否如此)。