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



我正在创建一个包含非ascii字符的文件。

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

错误信息是open: Invalid argument at C:tempfilename.pl line 15.

脚本在cmd.exe内启动。

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

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: $filenamen";
close $fh;

我可能错过了一些对其他人来说很明显的东西,但我找不到,所以我很感激任何指向解决这个问题的指针。

首先,说"UTF-8字符"很奇怪。UTF-8可以编码任何Unicode字符,因此UTF-8字符集就是Unicode字符集。这意味着您希望创建文件名包含Unicode字符的文件,更具体地说,是不在cp1252中的Unicode字符。

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


Perl将文件名视为不透明的字节串。这意味着文件名需要按照"区域设置"的编码(ANSI代码页)进行编码。

在Windows中,代码页1252通常被使用,因此编码通常是cp1252 .*然而,cp1252不支持泰米尔语和印地语字符[或"☺"]。

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

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

& # 42;本;代码页由GetACP系统调用返回(作为一个数字)。前置" cp "以获得编码

& # 42; & # 42;本;Perl对Windows的支持在某些方面很糟糕。

下面的程序在Windows 7, ActiveState Perl上运行。它将"hello there"写入文件名中含有希伯来字符的文件:

#-----------------------------------------------------------------------
# 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 theren";      
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: $filenamen";
close $fh;

HTH,保罗

相关内容

最新更新