-1

我有一个使用该SDBM_File模块的 Perl 绑定哈希,我需要在存储或获取值时进行一些字符编码转换。

我遵循了文档,perldbmfilter并且通常它似乎工作:我从哈希中得到结果,如预期的那样正确编码,并将我的编码的字节值存储在文件中,我使用十六进制编辑器进行检查。

不起作用的是对散列的所有元素进行任何类型的迭代,无论是使用keys、 或each或类似的东西Data::Dumper,甚至是简单的复制操作到另一个散列。

我总是得到的是无限递归。似乎迭代器永远不会结束,如果我使用each并打印迭代值,它们就会重复。

我将问题归结为filter_fetch_key我在那里进行的字符集转换的使用和转换。如果我注释掉filter_fetch_key,或者如果我将过滤器方法更改为 do just return shift,那么迭代将再次起作用。这些都解决了我的问题,但我需要使用filter_fetch_key来发送调用者正确编码的字符串。

$dbm->filter_fetch_key  (sub { $_ = $self->_normalizeCharset($_); });

sub _normalizeCharset
{
  my $self = shift || Carp::croak(...);

  #return shift;
  return ...::windows2utf(shift);
}

如果我取消注释return shift,则迭代有效;但像上面这样评论它没有。我想它与发生的事情有关$_,但我不知道,因为windows2utf只是复制给定的数据并进行一些字符编码。这与存储键和值甚至获取值的方式相同。只有键才是问题所在,而且只有当我进行迭代时,而不是我直接要求特定键时。

关于我做错了什么的任何提示?

还有一个线程Perlmonks

4

1 回答 1

1

我发现了问题:在测试过程中,我认识到filter_fetch_key使用键值调用我的函数一次,undef并且在这种情况下,为了方便起见,我的函数返回一个空字符串。这似乎是导致无限循环的原因,我猜有人出于某种原因想将该空字符串作为新键添加到哈希中,并且遇到了一些无效的迭代器等问题。有趣的部分是对键的更改应该非常好,因为文档中的一个示例正是关于此的,我的测试表明我可以替换每个键,除了undef我喜欢的任何键,我可以创建全新的例如,通过在前面加上 __ 键。没问题,只要我不undef回来undef我得到了无限循环。以下方法的第一个版本有效,第二个版本无效。

sub _normalizeCharset
{
  my $self  = shift || Carp::croak(...);
  my $value = shift;
  my $key = shift || 0;
return undef unless (defined($value));
#return '' unless (defined($value));

$value = "__$value" if ($key);

  return ...::windows2utf($value);
}


sub _normalizeCharset
{
  my $self  = shift || Carp::croak(...);
  my $value = shift;
  my $key = shift || 0;
#return undef unless (defined($value));
return '' unless (defined($value));

$value = "__$value" if ($key);

  return ...::windows2utf($value);
}

我想undef可能是过滤器的一些特殊信号,以指示迭代键的结束等,并且根本不意味着作为常规哈希键。至少我不会把它放在任何地方。

于 2014-09-09T09:35:54.570 回答