2011-05-13 37 views
5

創建Unicode文件名我有以下代碼你如何在Windows中使用Perl

use utf8; 
open($file, '>:encoding(UTF-8)', "さっちゃん.txt") or die $!; 
print $file "さっちゃん"; 

但我得到的文件名作爲•一個£ã¡ã,ƒã,「。TXT

我想知道是否有一種方法可以像我期望的那樣進行這項工作(意味着我有一個unicode文件名),而無需使用Win32 :: API,Win32API :: *或移動到另一個平臺並使用Samba共享來修改文件。

目的是確保我們沒有任何需要加載(甚至有條件地)的Win32特定模塊。

+1

它工作得很好(Windows XP,cygwin perl 5.10)。確定你有perl的問題,而不是一些其他的東西?你真的用UTF-8編碼保存源文件嗎? – n0rd 2011-05-13 13:56:02

+0

可能的重複[什麼是通用的方式來使用文件I/O API與Uni​​code文件名?](http://stackoverflow.com/questions/2796127/what-is-the-universal-way-to-use-file -io-api-with-unicode -names) – daxim 2011-05-13 14:36:25

+0

@ n0rd我使用的是ActiveState Perl而不是Cygwin – 2011-05-14 13:53:31

回答

5

Perl將文件名稱視爲不透明的字節字符串。它們需要按照您的「語言環境」的編碼(ANSI代碼頁)進行編碼。在Windows中,這通常是cp1252。它由系統調用GetACP返回。 (前置「cp」)。但是,cp1252不支持日文字符。 Windows也提供了一個「Unicode」又名「寬」接口,但Perl不提供使用內建*的訪問權限。不過,您可以使用Win32API :: File的CreateFileW。 IIRC,你仍然需要自己編碼文件名。如果是這樣,你會使用UTF-16le作爲編碼。

* — Perl在某些方面對Windows的支持很糟糕。

+0

這是正確的編碼cp1252產量?對於日文字符,因此它使它成爲無效的Windows文件名稱?文件名字符。 – 2011-05-14 14:05:08

+1

@Archimedes Trajano,你可以配置encode來返回除「?」之外的東西,這樣你就可以創建* valid * Windows文件名。然而,你不能使用'CreateFileA'(Perl使用的)來創建你想要的文件名。你必須使用'CreateFileW',並且Win32API :: File提供對它的訪問。 – ikegami 2011-05-14 21:20:13

+0

@ikegami這是正確的,但這就是爲什麼我在我原來的問題中表示不使用Win32API的東西,也不使用遠程Samba共享。 – 2011-05-15 01:05:33

0

使用Encode::Locale

use utf8; 
use Encode::Locale; 
use Encode; 

open($file, '>:encoding(UTF-8)', encode(locale_fs => "さっちゃん.txt")) or die $!; 
print $file "さっちゃん"; 
+0

看起來很有希望,但我似乎無法用Windows中的當前Perl安裝來構建Encode :: Locale。任何人驗證這一點 – 2012-05-04 22:15:16

+0

剛剛在運行「ppm安裝Encode-Locale」後在ActivePerl 5.12上進行了測試,並在「open」爲「Invalid arguent」的行上出現錯誤 – 2012-05-05 16:00:08

+0

在Windows上使用Strawberry Perl。 – godegisel 2012-09-05 14:28:18

1

下產生使用的ActiveState Perl的在Windows 7 unicoded文件名。

#----------------------------------------------------------------------- 
# Unicode file names on Windows using Perl 
# Philip R Brenan at gmail dot com, Appa Apps Ltd, 2013 
#----------------------------------------------------------------------- 

use feature ":5.16"; 
use Data::Dump qw(dump); 
use Encode qw/encode decode/; 
use Win32API::File qw(:ALL); 

# Create a file with a unicode name 

my $e = "\x{05E7}\x{05EA}\x{05E7}\x{05D5}\x{05D5}\x{05D4}". 
     "\x{002E}\x{0064}\x{0061}\x{0074}\x{0061}"; # File name in UTF-8 
my $f = encode("UTF-16LE", $e); # Format supported by NTFS 
my $g = eval dump($f);   # Remove UTF ness 
    $g .= chr(0).chr(0);   # 0 terminate string 
my $F = Win32API::File::CreateFileW 
($g, GENERIC_WRITE, 0, [], OPEN_ALWAYS, 0, 0); # Create file via Win32API 
say $^E if $^E;     # Write any error message 

# Write to the file 

OsFHandleOpen(FILE, $F, "w") or die "Cannot open file"; 
binmode FILE;      
print FILE "hello there\n";  
close(FILE);