【发布时间】:2013-06-29 13:45:51
【问题描述】:
我正在尝试以非缓冲方式读取 Perl 中的 UTF-8 输入(即,一旦数据可用,就应该返回它):
die if !binmode STDIN, ':unix:utf8';
my $i;
my $buf;
while ($i = read(STDIN, $buf, 8192)) {
print "$i\n";
}
但是,如果输入包含 UTF-8 字符分割,则它不起作用:
$ perl -e '$|=1;print"\xc3";sleep 1;print"\xa1";sleep 1;print"AB"' | perl t.pl
这应该先打印 1,然后再打印 2,但它会打印 3,因此即使第一个字符可用,缓冲也会保留它。
在 Perl 中有一个简单的解决方案吗?或者也许是另一种 Unix 脚本语言?
【问题讨论】:
-
我认为你不应该混合使用 :translators 和二进制
read。首先read你的缓冲区,然后Encode::decode它。正是因为字节字符串"\xc3"不是UTF-8 字符。 -
如果您正在读取 utf8 流,则没有“不必要的缓冲”。您必须至少有一个 6 到 8 字节的缓冲区,这样您就不会读取不完整的字符(这就是 perl 在您的示例中所做的)。 那是,因为我在谈论代码点。字形完全是另一回事。
-
您可以很好地执行
binmode STDIN, ':raw'; binmode STDOUT, ':raw',因为您没有对缓冲区进行任何其他处理。即使是不完整的 utf8 字符也会在管道的另一侧重新组装。 -
@Massa:我正在处理,但示例代码中没有说明。
-
@Massa:如果我在示例中将 AB 更改为 ABCDEFGHIJKLMNOP,Perl 仍然会在一批中返回所有内容。因此缓冲区大小大于 8 个字节。并且有不必要的缓冲,因为没有不必要的缓冲,我的示例应该打印 1 和 2,但它会打印 3。