11

我已经阅读了下一篇:

但可能错过了一些基本点。

使用

use open(:utf8);

也影响 cpan 模块?例如,当某些 CPAN 模块打开任何文件时,它会以:utf8? 这个说法是真的吗?(或者 open pragma 只是词法范围?)AFAIK - 它也影响模块,但是以“不一致”的方式..(可能是模块的问题)。

open pragma效果opendir吗?- 我已经尝试过 -- 我仍然需要额外decode的所有文件名来自readdir(除了 NFC)。所以,IO::Dir 是不同的——开放式编译指示没有涵盖哪些内容?

影响 open pragma sockets,管道也?(例如,什么是某种 IO::Handle ?)

所有(或大多数)CPAN 模块在执行 i/o 时都知道它们需要如何执行(utf8 或 lattin1 或 raw?)(可能不是,因为简单autodie的 pragma 不适用于open... :()

在很多地方我都能读到类似的规则:记住 Unicode 的规范规则:始终在应用程序的边缘进行编码/解码。这是一个很好的规则——但应用程序的优势意味着:我自己的源代码。CPAN 模块(通常)也位于边缘之后- 不仅是“外部世界”,如系统或网络......

根据我的经验,我的短脚本(大量使用 CPAN)的 3/4 内容包含:顶级声明,以及几乎所有内容的数十个编码/解码/NFC……

例如:即使是日志记录实用程序,也需要显式编码:

use Log::Any qw($log);
use Log::Any::Adapter ('File', 'file.log');
$log->error( encode('utf-8', "tökös"));

甚至,当想要添加到我的代码中时,需要用编码版本tie替换每个。$key $value

这是真的,还是我错过了上述所有内容中的一些非常基本的观点?

一些处理 utf8(内部)的 CPAN 模块,例如 JSON::XS、YAML::XS、File::Slurp..(尽管从未成功从 YAML::XS 获得正确的“东西”,但纯 YAML 和 JSON::XS 无需任何问题...

对于某些模块存在“黑客” - 比如DBIx::Class::ForceUTF8, Template::Stash::ForceUTF8, HTML::FillInForm::ForceUTF8- 等等, - 什么不允许为“两者” utf 和非 utf 世界编写正确的应用程序...... ;(

许多 CPAN 模块不会在内部调用上述“被破解的变体” - (例如HTML::FillInForm::ForceUTF8),而只是简单的,因此无法正确使用 utf8... 其他人,默默地失败.. ;(

如果没有烦人的“宽字符....”,Plack 应用程序无法处理 utf8日志消息;( /modern perl :(/ 并且可以继续;(

从上面我“扣除”(可能是错误的)——我必须知道并记住每个 CPAN 模块它是如何处理 utf8 编码的字符串的,并且因为没有一些“注册表”——主要是基于试验/错误的。

所以主要问题是:

虽然我记得:这不是灵丹妙药但这里有一些好方法如何检测和了解“ utf8 就绪 CPAN 模块”在使用它们之前不需要特殊编码/解码吗?

如果有人需要知道,我将在每个脚本中使用下一个:

use 5.014;
use warnings;
use utf8;
use feature qw(unicode_strings);
use charnames qw(:full);
use open(:utf8); #this sometimes is bad, so using only open qw(:std :utf8);
use Encode qw(encode decode);
use Unicode::Normalize qw(NFD NFC);

嗯 .. 刚刚“发现”了utf8:allperl 模块,它替换了readdir进行解码的版本。

4

1 回答 1

5

强调我的:

pragma用open作为所有 I/O 声明默认“层”(也称为“规程”)的接口之一。在这个 pragma的词法范围内找到的任何两个参数open, readpipe(aka qx//) 和类似的运算符都将使用声明的默认值。即使是三个参数的 s 也可能会受到这个 pragma 的影响,如果它们没有在.openMODE

所以不,它不会影响任何不存在编译指示的代码。但是,如果将在这种 pragma 范围内打开的句柄传递给 pragma 范围之外的代码,则不会丢失其层。


测试以查看模块的期望:

输入

  • 测试 1
    • 让输入源返回一个字符串,其中包含 80..FF 中的代码点,并且在 FF 之上没有代码点。
  • 测试 2
    • 让输入源返回一个包含 FF 以上代码点的字符串。

输出

  • 测试 1
    • 输出一个字符串,其中包含 80..FF 中的代码点,并且在 FF 之上没有代码点。首先通过字符串utf8::downgrade($_);
  • 测试 2
    • 与测试 1 相同,但首先传递字符串utf8::uprade($_);
  • 测试 3
    • 输出一个包含 FF 以上代码点的字符串
于 2013-07-01T15:49:40.537 回答