【问题标题】:Creating filenames with unicode characters使用 unicode 字符创建文件名
【发布时间】:2015-10-01 00:03:39
【问题描述】:

我正在寻找一些关于如何使用 Unicode 字符创建文件名的指南。考虑:

use open qw( :std :utf8 );
use strict;
use utf8;
use warnings;

use Data::Dump;
use Encode qw(encode);

my $utf8_file_name1 = encode('UTF-8', 'æ1', Encode::FB_CROAK | Encode::LEAVE_SRC);
my $utf8_file_name2 = 'æ2';
dd $utf8_file_name1;
dd $utf8_file_name2;
qx{touch $utf8_file_name1};
qx{touch $utf8_file_name2};
print (qx{ls æ*});

输出是:

"\xC3\xA61"
"\xE62"
æ1
æ2

为什么我是否将文件名编码为 UTF8 并不重要? (无论哪种方式,文件名仍然变为有效的 UTF8。)

【问题讨论】:

    标签: perl unicode utf-8


    【解决方案1】:

    因为一个名为“Unicode 错误”的错误。相当于发生了以下情况:

    use Encode qw( encode_utf8 is_utf8 );
    
    my $bytes = is_utf8($str) ? encode_utf8($str) : $str;
    

    is_utf8 检查标量使用了两种字符串存储格式中的哪一种。这是一个您永远不必担心的内部实现细节,除了 Unicode 错误。

    您的程序可以正常工作,因为encode 总是返回一个字符串,is_utf8 总是返回一个字符串,use utf8; 总是返回一个字符串,如果字符串包含非 ASCII 字符,is_utf8 就返回 true。

    如果您不按应有的方式encode,有时您会得到错误的结果。例如,如果您使用"\x{E6}2" 而不是'æ2',即使字符串具有相同的长度和相同的字符,您也会得到不同的文件名。

    $ dir
    total 0
    
    $ perl -wE'
       use utf8;
       $fu="æ";
       $fd="\x{E6}";
       say sprintf "%vX", $_ for $fu, $fd;
       say $fu eq $fd ? "eq" : "ne";
       system("touch", $_) for "u".$fu, "d".$fd
    '
    E6
    E6
    eq
    
    $ dir
    total 0
    -rw------- 1 ikegami ikegami 0 Jul 12 12:18 uæ
    -rw------- 1 ikegami ikegami 0 Jul 12 12:18 d?
    

    【讨论】:

    • 有趣,你有这个bug的参考吗?会修复吗?
    • 我怀疑有票。修复它可能会破坏比修复更多的代码。
    • 我很难理解这个错误是如何工作的..,但据我所知,结论是我应该始终使用例如 Encode::encode 对文件名进行编码(就像我对 $utf8_filename1 所做的那样)在创建文件之前?
    • 是的,你应该编码。实际发生的情况是使用字符串缓冲区而不检查 UTF8 标志
    • 更多关于“Unicode Bug”的信息可以在perlunicode找到
    猜你喜欢
    • 2015-08-20
    • 1970-01-01
    • 2017-08-21
    • 2011-08-24
    • 1970-01-01
    • 2023-03-06
    • 2011-01-19
    • 1970-01-01
    • 2018-03-03
    相关资源
    最近更新 更多