2017-01-23 30 views
3

我正在使用Perl對其名稱中包含非ASCII字符的文件進行存在檢查。即使文件存在,檢查總是返回false。我在Windows 10機器上使用Strawberry Perl v5.24.0。爲什麼-e文件存在測試對於包含非ASCII字符的文件名總是返回false?

這裏是我的代碼:

use strict; 
use warnings; 

use Encode; 

my $file = '<SOME DIR PATH>/áéíóú.mov'; 
if (-e $file) { 
    print "$file exists"; 
} else { 
    print " $file does not exists" ; 
} 

我也改變了代碼頁在CMD殼運行chcp 65001。 cmd然後能夠識別字符,但不知何故它總是返回此文件的「不存在」。

我該如何解決這個問題?

+0

你用什麼編碼保存你的腳本?如果它是UTF-8,那麼'使用utf8;'? – choroba

+0

您需要使用您的機器的「ANSI」編碼(cp1252?由'Win32 :: GetACP()'返回)來執行內置系統調用。 (chcp更改終端的OEM代碼頁,這與系統調用所使用的ANSI代碼頁無關。)Win32 :: Unicode提供了接受UTF-8或Unicode字符串的函數(我不記得是哪一個)。請記住'-e'只是'stat'的一個包裝。 – ikegami

+0

@ikegami如果我在cp1252中編碼文件名,它應該可以工作,但是我也會得到相同的輸出。 '$ file = encode(「cp1252」,$ file);'我jsut添加了這行,但仍然得到相同的輸出。 –

回答

5
use strict; 
use warnings; 

# Properly decode source code, which is expected to be UTF-8. 
# This allows non-ASCII characters in the source. 
use utf8; 

# Properly decode text received from STDIN. 
# Properly encode text sent to STDOUT and STDERR. 
use Win32 qw(); 
my ($enc_in, $enc_out, $enc_syscall); 
BEGIN { 
    $enc_input = 'cp'.Win32::GetConsoleCP(); 
    $enc_output = 'cp'.Win32::GetConsoleOutputCP(); 
    $enc_syscall = 'cp'.Win32::GetACP(); 

    binmode STDIN, ":encoding($enc_input)"; 
    binmode STDOUT, ":encoding($enc_output)"; 
    binmode STDERR, ":encoding($enc_output)"; 
} 

use Encode qw(encode); 

my $file = 'áéíóú.mov'; 

if (-e encode($enc_syscall, $file, Encode::FB_CROAK | Encode::LEAVE_SRC)) { 
    print("$file exists\n"); 
} 
elsif ($!{ENOENT}) { 
    print("$file doesn't exist\n"); 
} 
else { 
    die("Can't determine if \"$file\" exists: $!\n"); 
} 

use strict; 
use warnings; 

# Properly decode source code, which is expected to be UTF-8. 
# This allows non-ASCII characters in the source. 
use utf8; 

# Properly decode text received from STDIN. 
# Properly encode text sent to STDOUT and STDERR. 
use Win32 qw(); 
my ($enc_in, $enc_out, $enc_syscall); 
BEGIN { 
    $enc_input = 'cp'.Win32::GetConsoleCP(); 
    $enc_output = 'cp'.Win32::GetConsoleOutputCP(); 
    $enc_syscall = 'cp'.Win32::GetACP(); 

    binmode STDIN, ":encoding($enc_input)"; 
    binmode STDOUT, ":encoding($enc_output)"; 
    binmode STDERR, ":encoding($enc_output)"; 
} 

use Win32::Unicode::File qw(statW); 

my $file = 'áéíóú.mov'; 

if (statW($file)) { 
    print("$file exists\n"); 
} 
elsif ($!{ENOENT}) { 
    print("$file doesn't exist\n"); 
} 
else { 
    die("Can't determine if \"$file\" exists: $^E\n"); 
} 

後者不限於包含機器的ANSI字符集的字符的路徑。

+0

謝謝,它的工作,我意識到我的錯誤。出於好奇,以前的評論部分(你問的)的輸出是什麼,如果我想了解更多關於這個問題的地方,我可以去哪裏? –

+0

另外,當我將所有使用語句放在BEGIN塊中時,上面的代碼再次給出輸出,因爲文件不存在。爲什麼? –

+1

組成字符串的字符的值(十六進制)。 ///'使用utf8;'是詞彙範圍的。 – ikegami

相關問題