【问题标题】:Perl 6 $*ARGFILES.handles in binary mode?Perl 6 $*ARGFILES.handles 在二进制模式下?
【发布时间】:2018-12-05 19:52:47
【问题描述】:

我正在尝试 $*ARGFILES.handles,它似乎以二进制模式打开文件。

我正在编写一个 zip-merge 程序,它从每个文件中打印一行,直到没有更多行可供读取。

#! /usr/bin/env perl6

my @handles = $*ARGFILES.handles;

# say $_.encoding for @handles;

while @handles
{
  my $handle = @handles.shift;
  say $handle.get;
  @handles.push($handle) unless $handle.eof;
}

我这样调用它:zip-merge person-say3 repeat repeat2

它失败了:无法在 ./zip-merge 第 7 行的块中以二进制模式对句柄执行“获取”

指定的文件是文本文件(以 utf8 编码),我收到了关于不可执行文件和可执行文件(使用 perl6 代码)的错误消息。

注释掉的行说我给它的每个文件都是utf8,所以它们不应该是二进制的,

perl6 -v:这是基于 MoarVM 版本 2018.10 构建的 Rakudo 版本 2018.10

我做错了什么,还是发现了错误?

【问题讨论】:

  • 能否提供一个或多个示例文件?
  • 将程序另存为“zip-merge”并使用“zip-merge zip-merge”自行运行。

标签: raku


【解决方案1】:

.handles 返回的 IO::Handle 对象已关闭。

my @*ARGS = 'test.p6';
my @handles = $*ARGFILES.handles;
for @handles { say $_ }
# IO::Handle<"test.p6".IO>(closed)

如果您只想让您的代码正常工作,请在分配给@handles 之后添加以下行。

.open for @handles;

原因是.handles 的迭代器是用IO::CatHandle.next-handle 编写的,它打开当前句柄并关闭前一个句柄。
问题是,在您有机会对它们进行任何工作之前,它们都有机会成为当前句柄和前一个句柄。
(也许.next-handle 和/或.handles 需要:!close 参数。)


假设您希望它像 roundrobin 那样工作,我实际上会写得更像这样:

# /usr/bin/env perl6
use v6.d;

my @handles = $*ARGFILES.handles;

# a sequence of line sequences
my $line-seqs = @handles.map(*.open.lines);
# Seq.new(
#   Seq.new( '# /usr/bin/env perl6', 'use v6.d' ), # first file
#   Seq.new( 'foo', 'bar', 'baz' ),                # second file
# )

for flat roundrobin $line-seqs {
  .say
}

# `roundrobin` without `flat` would give the following result

# ('# /usr/bin/env perl6', 'foo'),
# ('use v6.d', 'bar'),
# ('baz')

如果您为$line-seqs 使用了数组,则需要在将值传递给roundrobin 之前对它们进行去项目化(.&lt;&gt;)。

for flat roundrobin @line-seqs.map(*.<>) {
  .say
}

其实我个人更可能写出类似这种(长)单行字的东西。

$*ARGFILES.handles.eager».open».lines.&roundrobin.flat.map: *.put

【讨论】:

  • 在我的代码中,句柄是打开的。一个小测试表明:say $_ for $*ARGFILES.handles;使用现有文件调用它,例如"ack6": ./argfile-handle ack6 IO::Handle(opened) 问题是它们是以二进制方式打开的。
  • @ArneSommer 是的,我看过这个。迭代器的编写方式作为迭代的一部分被打开和关闭。它仅在迭代期间打开;之后他们都关闭了。还有一个错误,.get 返回错误的错误。它们不是二进制模式。如果您不相信我,请尝试致电read
  • @ArneSommer 作为进一步的证明:say $_ for flat $*ARGFILES.handles.rotor(2 =&gt; -1,:partial); 会在说它打开和说它关闭之间交替。
  • 谢谢。错误消息是 LTA。我希望它被打勾了?
【解决方案2】:

:binalways set in this type of objects。由于您正在处理句柄,因此您应该按照示例中的说明逐行阅读,或者重置句柄以使其不处于二进制模式。

【讨论】:

  • 好的。我没看过那个部分。但它说如果使用 $*IN 则它是二进制的,这是 @*ARGS 而不是 $*IN。
  • 在句柄上使用 .encoding 会得到“utf8”,对于以二进制模式打开的文件肯定不会给出?
  • “逐行阅读”是什么意思?当然,我正在这样做。将 $handle.get; 更改为 $handle.lines: 1;(如示例中所做的那样)也会失败。
  • 我认为该行的意图是如果$*ARGFILES 使用$*IN,它会从$*IN 复制这些属性。
  • 它们不是二进制模式,它返回该错误是一个错误。如果它们处于二进制模式,encoding 将是 Nil,但事实并非如此。只需运行.encoding.say for @handles;,它就会为所有人显示utf8
猜你喜欢
  • 1970-01-01
  • 2011-12-16
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多