1

我正在使用MARC::Lintlint 一些 MARC 记录,但现在我遇到了一个错误(大约 1% 的文件):

utf8 "\xCA" does not map to Unicode at /usr/lib/x86_64-linux-gnu/perl/5.26/Encode.pm line 212.

问题是我尝试了不同的方法,但在文件中找不到"\xCA"...

我的脚本是:

#!perl -w
use MARC::File::USMARC;
use MARC::Lint;
use utf8;

use open OUT => ':utf8';

my $lint = new MARC::Lint;
my $filename = shift;

my $file = MARC::File::USMARC->in( $filename );
while ( my $marc = $file->next() ) {
    $lint->check_record( $marc );
    # Print the errors that were found
    print join( "\n", $lint->warnings ), "\n";
} # while

文件可以在这里下载:http: //eroux.fr/I14376.mrc

“\xCA”是否隐藏在某处?或者这是 MARC::Lint 中的错误?

4

1 回答 1

3

这个问题与 MARC::Lint 无关。删除 lint 检查,您仍然会收到错误消息。

问题是错误的数据文件。

该文件包含信息在文件中所在位置的“目录”。以下是您提供的文件的目录的可读版本:

tagno|offset|len   # Offsets are from the start of the data portion.
001|00000|0017     # Length include the single-byte field terminator.
006|00017|0019     # Offset and lengths are in bytes.
007|00036|0015
008|00051|0041
035|00092|0021
035|00113|0021
040|00134|0018
050|00152|0022
066|00174|0009
245|00183|0101
246|00284|0135
264|00419|0086
300|00505|0034
336|00539|0026
337|00565|0026
338|00591|0036
546|00627|0016
500|00643|0112
505|00755|9999  <--
506|29349|0051
520|29400|0087
533|29487|0115
542|29602|0070
588|29672|0070
653|29742|0013
710|29755|0038
720|29793|0130
776|29923|0066
856|29989|0061
880|30050|0181
880|30231|0262

注意带有标签 505, 的字段的长度9999。这是支持的最大值(因为长度存储为四位十进制数字)。问题是该字段的值远大于 9,999 字节;它实际上是 28,594 字节大小。

发生的情况是模块提取了 9,999 个字节而不是 28,594 个字节。这恰好将 UTF-8 序列减半。(具体的顺序是 CA BA,的编码ʼ。)稍后,当模块尝试解码该文本时,会抛出错误。(CA必须后跟另一个字节才有效。)

您正在生成这些记录吗?如果是这样,您需要确保没有字段需要超过 9,999 个字节。

尽管如此,该模块应该更好地处理这个问题。它可以读取直到它找到一个字段结束标记,而不是在它没有找到它期望的字段结束标记和/或它可以以非致命方式处理解码错误时使用长度。它已经有一个机制来报告这些问题($marc->warnings)。

事实上,如果它没有死(比如说,如果剪切发生在字符之间而不是在字符中间),$marc->warnings将返回以下消息:

field does not end in end of field character in tag 505 in record 1
于 2019-07-23T14:23:58.327 回答