如何在Perl中编写一个* filename *包含utf8字符的文件?

我正在努力创build一个包含非ASCII字符的文件。

如果以0作为参数调用下面的脚本,但使用1调用时会死亡。

错误消息已打开:C:\ temp \ filename.pl第15行中的参数无效。

该脚本在cmd.exe启动。

我期望它写一个文件的名字是(取决于参数) äöü.txtäöü☺.txt 。 但我无法创build包含笑脸的文件名

 use warnings; use strict; use Encode 'encode'; # Text is stored in utf8 within *this* file. use utf8; my $with_smiley = $ARGV[0]; my $filename = 'äöü' . ($with_smiley ? '☺' : '' ). '.txt'; open (my $fh, '>', encode('cp1252', $filename)) or die "open: $!"; print $fh "Filename: $filename\n"; close $fh; 

我可能错过了一些对别人显而易见的东西,但是我找不到,所以我会很感激任何解决这个问题的指针。

Solutions Collecting From Web of "如何在Perl中编写一个* filename *包含utf8字符的文件?"

首先,说“UTF-8字符”是奇怪的。 UTF-8可以编码任何Unicode字符,所以UTF-8字符集是Unicode字符集。 这意味着您要创建名称中包含Unicode字符的文件,更具体地说,是不在cp1252中的Unicode字符。

我以前在PerlMonks上回答过这个问题。 下面复制的答案。


Perl将文件名称视为不透明的字节串。 这意味着文件名需要根据你的“locale”的编码(ANSI代码页)进行编码。

在Windows中,代码页1252是常用的,因此编码通常是cp1252 。*但是, cp1252不支持泰米尔语和印地语字符[或“☺”]。

Windows也提供了一个“Unicode”又名“宽”的接口,但是Perl不能使用内置的**来访问它。 不过,您可以使用Win32API :: File的CreateFileW 。 IIRC,你仍然需要自己编码文件名。 如果是这样,你会使用UTF-16le作为编码。

前面提到的Win32 :: Unicode似乎是为你处理一些使用Win32API :: File的肮脏工作。 我也建议从那开始。

* – GetACP系统调用返回代码页(以数字形式)。 预先加上“ cp ”来获得编码。

** – Perl在某些方面对Windows的支持很糟糕。

以下是在Windows 7上运行的ActiveState Perl。 它将“hello there”写入一个名为hebrew字符的文件中:

 #----------------------------------------------------------------------- # 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); 

不需要编码文件名(至少不是在Linux上)。 这段代码适用于我的linux系统:

 use warnings; use strict; # Text is stored in utf8 within *this* file. use utf8; my $with_smiley = $ARGV[0] || 0; my $filename = 'äöü' . ($with_smiley ? '?' : '' ). '.txt'; open my $fh, '>', $filename or die "open: $!"; binmode $fh, ':utf8'; print $fh "Filename: $filename\n"; close $fh; 

HTH,保罗