加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 关于路径名编码的问题

发布时间:2020-12-15 23:25:19 所属栏目:大数据 来源:网络整理
导读:我在这个路径名中做了什么奇怪的编码呢? 在我的文件管理器(Dolphin)中,路径名称看起来很好. #!/usr/local/bin/perluse warnings;use 5.014;use utf8;use open qw( :encoding(UTF-8) :std );use File::Find;use Devel::Peek;use Encode qw(decode);my $strin
我在这个路径名中做了什么奇怪的编码呢?
在我的文件管理器(Dolphin)中,路径名称看起来很好.

#!/usr/local/bin/perl
use warnings;
use 5.014;
use utf8;
use open qw( :encoding(UTF-8) :std );
use File::Find;
use Devel::Peek;
use Encode qw(decode);

my $string;
find( sub { $string = $File::Find::name },'Delibes,Léo' );
$string =~ s|Delibes, ||;
$string =~ s|..*z||;
my ( $s1,$s2 ) = split m|/|,$string,2;

say Dump $s1;
say Dump $s2;

# SV = PV(0x824b50) at 0x9346d8
#   REFCNT = 1
#   FLAGS = (PADMY,POK,pPOK,UTF8)
#   PV = 0x93da30 "L303251o" [UTF8 "Lx{e9}o"]
#   CUR = 4
#   LEN = 16

# SV = PV(0x7a7150) at 0x934c30
#   REFCNT = 1
#   FLAGS = (PADMY,UTF8)
#   PV = 0x7781e0 "Lakm303203302251" [UTF8 "Lakmx{c3}x{a9}"]
#   CUR = 8
#   LEN = 16

say $s1;
say $s2;

# Léo
# Lakm??

$s1 = decode( 'utf-8',$s1 );
$s2 = decode( 'utf-8',$s2 );

say $s1;
say $s2;

# L?o
# Lakmé

解决方法

不幸的是,您的操作系统的路径名API是另一个“二进制接口”,您必须使用Encode :: encode和Encode :: decode来获得可预测的结果.

大多数操作系统将路径名视为八位字节序列(即字节).该序列是否应解释为latin-1,UTF-8或其他字符编码是应用程序决策.因此,readdir()返回的值只是一个八位字节序列,而File :: Find不知道您希望路径名称为Unicode代码点.它通过简单地连接目录路径(您提供的)与您的操作系统通过readdir()返回的值来形成$File :: Find :: name,这就是您如何获得与八位字节混合的代码点.

经验法则:每当将路径名传递给操作系统时,请使用Encode :: encode()来确保它是一个八位字节序列.从操作系统获取路径名时,将Encode :: decode()编码为应用程序所需的字符集.

您可以通过以下方式调用find来使您的程序正常工作:

find( sub { ... },Encode::encode('utf8',Léo') );

然后在使用$File :: Find :: name的值时调用Encode :: decode():

my $path = Encode::decode('utf8',$File::Find::name);

为了更清楚,这就是$File :: Find :: name的形成方式:

use Encode;

# This is a way to get $dir to be represented as a UTF-8 string

my $dir = 'L' .chr(233).'o'.chr(256);
chop $dir;

say "dir: ",d($dir); # length = 3

# This is what readdir() is returning:

my $leaf = encode('utf8','Lakem' . chr(233));

say "leaf: ",d($leaf); # length = 7

$File::Find::name = $dir . '/' . $leaf;

say "File::Find::name: ",d($File::Find::name);

sub d {
  join(' ',map { sprintf("%02X",ord($_)) } split('',$_[0]))
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读