2010-11-20 148 views
3

我正在努力處理包含非英文字符(Activestate Perl,Windows XP)的路徑。如何打開,寫入,複製位於路徑中的文件,並說出希臘語/俄語/法語重音字符?比方說,我想複製我的text.txt文件的目錄是:C:\Documents and Settings\στα\DesktopPerl:在Windows上管理路徑編碼

use File::Spec; 
my $save = File::Spec->canonpath($mw->chooseDirectory()); 

my $file = catfile($save , "renamed_text.txt"); 

my $input = "üüü\text.txt"; 
copy ($input, $file) or die "File cannot be copied."; 
+1

你的代碼片段有一個問題:你想要「\\ text.txt」而不是「\ text.txt」。這可能不是你最後的問題。 – Leolo 2010-11-21 06:08:30

回答

0

Perl的原生功能無法在這種情況下使用。使用支持Unicode字符的Win32模塊中的函數。 Win32首次與perl v5.8.7發佈。

+0

謝謝你的建議。除非(Win32 :: CopyFile($ input,$ ansi_path,1))我改變腳本爲 if($ err == ERROR_ALREADY_EXISTS){ 警告「目錄存在,沒有問題\ n」; } else { die Win32 :: FormatMessage($^E); } }但它不適用於希臘!任何想法? – Richard 2010-11-20 12:00:37

+0

對不起。目前我沒有Windows系統進行測試。如果我能夠測試,我會更新我的答案。 – 2010-11-20 15:06:46

+0

艾倫的答案是正確的,但不正確。您*可以*使用Perl的本地函數和寬字符編碼,但是在將文件名交給Perl之前,您必須將文件名編碼爲系統編碼。看到我的答案。 – 2010-12-19 06:13:34

2

幾年前,我在一個項目中遇到了同樣的問題(我們的PAR包裝GUI應用程序必須在Shift-JIS編碼下工作)。我嘗試了很多技術來讓Perl 5.8自動執行此操作。最後,我冗長而有效的解決方案是在將每個文件名傳遞給內置函數之前對其進行編碼。

首先,設置實用功能:

use Encode; 
use Win32::Codepage; 
my $encoding = Win32::Codepage::get_encoding() || q{}; 
if ($encoding) { 
    $encoding = Encode::resolve_alias($encoding) || q{}; 
} 
sub encode_filename { 
    my ($filename) = @_; 
    return $encoding ? encode($encoding, $filename) : $filename; 
} 

然後,用它到處

next if (! -d encode_filename($tmpldir)); 
my $file = SWF::File->new(encode_filename($dest)); 
@entries = File::Slurp::read_dir(encode_filename($srcdir)); 
etc... 

我甚至寫了一個小檢查,以確保我用它無處不在!

egrep "\-[a-zA-Z] |open[^_]|[^ ]parse|unlink|symlink|mkdir[^_]|mkpath|rename[^\']|File::Copy::copy|rmtree|getTemplate[^D]|write_file|read_file|read_dir" *.pl `find lib -name '*.pm'` | grep - 
v encode_filename | egrep -v '^[^:]+: *(\#|_announce|debug)' 

如果你錯過連一個,你會得到「寬字符」在運行時警告...

2

我沒有權限投票了從克里斯·多蘭的答案,但我有在日本使用基於Win32::Codepage的相同解決方案解決了路徑名稱的問題。

這可能需要確認,但我認爲Perl對所有非A​​SCII路徑名都採用UTF8。在Linux和OS X上,這可以正常工作,因爲操作系統路徑名以UTF8編碼。但是,在較早版本的Windows(Windows 7之前版本)中,路徑名是在該國的語言環境中編碼的(例如,日本的Shift-jis)。所以,返回非ASCII字符路徑名的所有Perl調用都會搞砸。

我使用的解決方案是使用Win32:Codepage查找語言環境編碼,然後在讀取文件時將其編碼爲UTF8。然後,在寫入(或更新)文件時,我會解碼回到區域設置編碼。

+1

你在上面的答案中有一點不正確。 Perl默認使用8位Latin-1編碼字符串。像Shift-JIS一樣,Latin-1是ASCII的超集。 – 2010-12-23 15:27:18

+0

您的投票給了我評論權限。謝謝! – Lozzer 2010-12-27 11:09:19

+0

對不起,以上錯誤。是的,它是拉丁語1.主要的一點是Perl使用UTF8,它在Windows系統上混淆了路徑名。我仍然感到驚奇的是,你不能在Perl中使用簡單的「打開」命令(在非拉丁語的Windows系統上)而不會搞亂Win32 :: Codepage。 – Lozzer 2010-12-27 11:15:42

0

我發現我必須在Microsoft Windows Vista上禁用UAC(User Access Control)才能成功安裝Win32::LocaleWin32::Codepage。 (謝謝克里斯多蘭,編寫後一個模塊。)

0

我在Windows 7和更新版本上也遇到了UAC(用戶訪問控制)問題。 我終於發現,自從Windows Vista以來,對所需註冊表項的訪問只具有讀權限。 您可以輕鬆地修補的Win32 ::代碼頁沒有管理權限的工作,如果你在你最喜歡的編輯器中打開該文件並替換:

$codekey = Win32::TieRegistry->new($CODEPAGE_REGISTRY_KEY, 
            { Delimiter => "/" } 
            ); 

    $codekey = Win32::TieRegistry->new($CODEPAGE_REGISTRY_KEY, 
            { Access=>"KEY_READ", Delimiter => "/" } 
            ); 

這對我的幫助安裝。

+1

這與文件路徑中的重音字符有什麼關係? – 2015-11-26 00:25:52