2011-09-25 77 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,具體取決於路徑上的各種文件系統如何處理編碼(以及它們是否如此)。