【问题标题】:How to create a file containing Unicode characters in its filename with open in a portable way?如何以可移植的方式打开文件名中包含 Unicode 字符的文件?
【发布时间】:2021-10-26 16:20:57
【问题描述】:

我有一个包含 Unicode 字符的 perl 字符串,我想用这个字符串作为文件名创建一个文件。无论使用何种语言环境,它都应该适用于 Windows、Linux 和 Mac。 这是我的代码:

use strict;
use warnings FATAL => 'all';

use Encode::Locale;
use Encode;

# ファイル.c
my $file = "\x{30D5}\x{30A1}\x{30A4}\x{30EB}.c";

$file = encode(locale_fs => $file);

open(my $filehdl, '>', $file) or die("Unable to create file: $!");
close($filehdl);

我使用encode 函数,因为根据这个answer

Perl 将文件名视为不透明的字节字符串。它们需要按照您的“区域设置”的编码(ANSI 代码页)进行编码。

但是,此代码失败并出现以下错误:

无法创建文件:.\perl.pl 第 15 行的参数无效。

我更深入地了解了encode如何对字符串进行编码:

my $rep = sprintf '%v02X', $file;
print($rep);

打印出来:

3F.3F.3F.3F.2E.63

在我当前的语言环境 (CP-1252) 中,它对应于 ????.c。我们可以看到每个 Unicode 字符都被一个问号代替了。 我认为这里有问号是正常的,因为我的字符串中的字符无法使用 CP-1252 编码表示。

所以,我的问题是:有没有办法创建一个名称包含 Unicode 字符的文件?

【问题讨论】:

  • 只是,你不能。不能保证文件系统支持 Unicode,并且每个操作系统都有允许使用哪些字符的特殊情况。我们还没有准备好。
  • @GiacomoCatenazzi 你的意思是,即使我确定我的操作系统可以创建文件(如果我直接使用文件资源管理器就是这种情况),我也无法为此编写可移植代码对吧?
  • 不清楚你想象的应该是什么意思。如果操作系统和文件系统支持 UTF-8,那么使用它应该很简单;但当然,他们这样做的假设是不可移植的。
  • 我会很惊讶有一种可移植的方式(并且在同一操作系统中也可移植,但不同的用户、不同的文件系统 [例如 USB 记忆棒、外部磁盘])等)。但是让我们看看是否有人有解决方案。
  • 如果您使用的是 Windows,另请参阅 Win32::Unicode::Filethis 问题

标签: perl unicode encoding


【解决方案1】:

对于 Windows,有一个模块 Win32::LongPath,它不仅允许长文件名,还允许 unicode 字符。

我为自己编写了一个模块,用于我需要的各种文件和目录 IO,在 Windows 上使用这些模块的功能,以及标准的 perl 功能,如下所示:

use Carp;
use Fcntl qw( :flock :seek );
use constant USE_LONG => ($^O =~ /Win/i) ? 1 : 0;
use if USE_LONG, 'Win32::LongPath', ':funcs';

sub open
{
    my $f       = shift; # file
    my $m       = shift;    # mode
    my $l       = @_ ? (shift) : 'utf8';    # encoding
    my $lock    = $m eq '<' ? LOCK_SH : LOCK_EX;
    length $l
        and $m .= ":$l";
    my $h;
    USE_LONG ? openL( \$h, $m, $f ) : open( $h, $m, $f ) # openL needs REF on Handle!
        or confess "Can't open file: '$f' ($^E)";
    flock( $h, $lock );
    return $h;
}

这样代码是可移植的。它可以在 Linux 服务器上运行,也可以在我家中的 Windows PC 上运行。

【讨论】:

  • 很遗憾,Win32::LongPath 软件包在我的系统上不可用(我无法安装它)。
  • 您的系统是 Windows 系统吗?如果是,你知道为什么不能安装吗?
  • 我只能使用我公司认可的perl包。要一个新的并不容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
相关资源
最近更新 更多