为什么Perl会在Windows上丢失外来字符;这可以修复(如果是这样,如何)?

时间:2010-12-24 16:01:47

标签: perl unicode windows-7

请注意以下ã更改为a 的方式。注意2:在将此错误归咎于CMD.EXE和Windows管道怪异之前,请参阅下面的实验2,它使用File :: Find获得类似的问题。

我正在尝试解决的特殊问题涉及处理存储在本地驱动器上的图像文件,以及操作可能包含外来字符的文件名。下面显示的两个实验是中间调试步骤。

ã字符在拉丁语中很常见。例如 http://pt.wikipedia.org/wiki/Cão

实验1

仔细观察,注意cão成为cao的方式。 alt text

实验2

这里我尝试使用File :: Find而不是管道输入,以防问题是| shell运算符的Windows实现。由于~a变为Pi,问题实际上会变得更糟: alt text


调试更新:

我尝试了http://perldoc.perl.org/perlunicode.html列出的一些技巧, 例如use utf8use feature 'unicode_strings'等无济于事。


环境和版本信息

操作系统是Windows 7,64位。

Perl是:

This is perl 5, version 12, subversion 2 (v5.12.2) built for MSWin32-x64-multi-thread
(with 8 registered patches, see perl -V for more detail)

Copyright 1987-2010, Larry Wall

Binary build 1202 [293621] provided by ActiveState http://www.ActiveState.com
Built Sep  6 2010 22:53:42

2 个答案:

答案 0 :(得分:6)

与许多其他脚本语言一样,Perl构建于C运行时。

在Windows上,窄(字节)字符的标准MS C运行时使用默认为Windows系统编码('ANSI代码页')的编码,用于IO活动,例如打开文件或写入控制台。

ANSI代码页始终是特定于语言环境的编码:通常是单字节,但在某些语言环境中是多字节的(例如中国,日本等)。它永远不是UTF-8或其他能够再现整个Unicode的东西; Perl IO可以处理的字符取决于Windows语言环境(“非Unicode程序的语言”设置)。

虽然可以使用chcp 65001命令为控制台应用程序提供UTF-8,但是这样做会产生许多严重的不一致。这给Windows上的很多工具带来了困难,这是微软真正需要解决的问题,但到目前为止他们的态度是Unicode等于UTF-16;每个想要使用Unicode的人都必须使用widechar接口。

因此,您目前无法在Windows上的Perl中可靠地处理使用非ASCII文件名的文件。遗憾。

您可以尝试使用Python(其中添加了特殊的Windows文件名处理以在2.3版本以后解决此问题;请参阅PEP 277)或其中一种支持Unicode的Windows Scripting Host语言。无论哪种方式,在Windows上将Unicode输出到控制台仍然有更多的陷阱。

答案 1 :(得分:1)

以下3个衬垫在我新推出的ActivePerl 5.12.2上按预期工作:

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

我认为罪魁祸首是cmd.exe。