文本 -T 和 PDF 的 Perl 文件测试

Posted

技术标签:

【中文标题】文本 -T 和 PDF 的 Perl 文件测试【英文标题】:Perl File Test for Text -T and PDFs 【发布时间】:2012-04-07 23:21:46 【问题描述】:

我正在尝试将我的 Perl-Tk 代码限制为仅打开要编辑的文本文件。我正在测试以确保用户选择了一个有效的文件(我正在使用 Tks getOpenFile() ):

if ( (defined $file) and (-f $file) and (-T $file) ) 
  #work with file

我遇到的问题是某些 PDF 文件通过了 -T 测试并被打开(导致混乱)。我在一个充满 PDF 的目录中尝试了这段代码:

#!/usr/bin/perl

use strict;
use warnings;

my @files = <*>;
foreach (@files) 
  if (-T)  print "$_ is a text file\n";

大约 1/2 的目录中的 PDF 被打印出来。

我使用 -T 错误吗?我是否必须添加正则表达式来过滤掉 PDF? Perl 怎么会认为只有部分 PDF 是文本?

编辑:-T 是一个文件测试,如果文件是纯文本,则应该返回 true。我不是要检查污点。

【问题讨论】:

PDF 可以是有效的纯文本文件。您是否可能在文本编辑器中检查了其中一个作为纯文本命中的文件? 这就解释了!只有文本的 PDF 通过,大多数图形的不通过 【参考方案1】:

使用File::Type 或File::LibMagic 模块可能会更成功。

PDF 主要是纯文本。压缩、图像和加密使它们显示为二进制。但简单的 PDF 文件对于天真的测试来说是纯文本。

规范中的minimal PDF 是纯文本:

%PDF-1.1
%íì¦"

1 0 obj
  << /Type /Catalog
     /Pages 2 0 R
  >>
endobj

2 0 obj
  << /Type /Pages
     /Kids [3 0 R]
     /Count 1
     /MediaBox [0 0 300 144]
  >>
endobj

3 0 obj
  <<  /Type /Page
      /Parent 2 0 R
      /Resources
       << /Font
           << /F1
               << /Type /Font
                  /Subtype /Type1
                  /BaseFont /Times-Roman
               >>
           >>
       >>
      /Contents [
        << /Length 105 >>
        stream
          BT
            /F1 18 Tf
            0 0 Td
            (Hello world.) Tj
          ET
        endstream ]
  >>
endobj

xref
0 4
0000000000 65535 f 
0000000019 00000 n 
0000000078 00000 n 
0000000179 00000 n 
trailer
  <<  /Root 1 0 R
      /Size 4
  >>
startxref
612
%%EOF

【讨论】:

我想就是这样,我从来没有想过 PDF 只能是文本。我会试试 File::Type。谢谢 File::LibMagic 比任何other detection module 做得更好。改用它。 -- libmagic 也是该问题的另外两个答案中提到的file 命令的基础。 取点,添加到答案中。 谢谢,我也去看看【参考方案2】:

您正确使用了-T:这只是一个最佳猜测,而不是绝对分类。知道 PDF 文件带有一个 4cc 的 %PDF 可能会有所帮助,您可以使用这样的子程序轻松检查它

sub isPDF 
  open my $fh, '<', shift or return;
  read $fh, my $fourcc, 4;
  return $fourcc eq '%PDF';

【讨论】:

【参考方案3】:

大多数 PDF 在 %PDF 之后都有一些二进制字符,目的是暗示它不是(完全)纯文本文件。 PDF 规范甚至推荐它:

注意:如果 PDF 文件包含二进制数据,大多数情况下(参见第 3.1 节, “词汇约定”),建议标题行是 紧随其后的是一个包含至少四个二进制文件的注释行 字符——即代码为 128 或更大的字符。这 将确保文件传输应用程序的正确行为 检查文件开头附近的数据以确定是否 将文件的内容视为文本或二进制文件。

在@mugen kenichi 的回答中,您可以看到%íì¦" 尝试触发此操作。

【讨论】:

【参考方案4】:

几个建议:

您是否尝试过使用较新的 Perl?文档将 -T 称为“启发式猜测”,也许他们对其进行了改进。 有点骇人听闻,但您可以尝试在打开文件之前对文件运行“文件” 另一个技巧:阅读 open() 之后的第一行,看看它确实是文本。

不知道为什么它会失败.. 你有通过 -T 的可公开访问的 pdf 文件吗?

【讨论】:

所有这些都被我的 Perl 5.12 ECMA 262、Java Language Specification 和 Data Structures and Algorithms 归类为 text 我的第三点应该有效。我称其为 hack,因为我不知道 pdf 标准,并且第一行可能不需要“%PDF”..【参考方案5】:

正如@yvind Skaar 指出的那样,尝试“文件”命令。

【讨论】:

以上是关于文本 -T 和 PDF 的 Perl 文件测试的主要内容,如果未能解决你的问题,请参考以下文章

Azure 计算机视觉 API - PDF 文件上的 OCR 到文本

创建一个 perl 脚本来批处理文件

Perl:在多个文本文件中查找和替换特定字符串

#Perl#使用perl合并多个文本

perl分割文件

Perl - 如何从文本文件中省略行?