65.9K
CodeProject 正在变化。 阅读更多。
Home

PDF 页数计数器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (7投票s)

2014年10月24日

CPOL

2分钟阅读

viewsIcon

37640

downloadIcon

2135

快速计算 PDF 文档集合中的页面数量

引言

我的公司 Red Cell Innovation Inc. 提供文档扫描服务。我们经常需要统计一批 PDF 文件的页数,用于计费、质量控制、排程和估算。

这是我快速编写的一个应用程序,以方便完成这项工作。该应用程序使用过程化风格,在单个简单的代码后台类中用大约 200 行代码(包括 XAML 和注释)实现此功能。

特点

  • 简单:将一个目录拖放到应用程序中。
  • 快速:扫描了 20GB 的 PDF 文件,并在 7 秒内(在网络驱动器上为 270 秒)统计了 499 个文件中的 53877 页,使用 SSD。

工作原理

语言 C# 5.0
.NET Framework 4.5
UI 框架 WPF
iTextSharp
模式 代码后台过程化

当应用程序启动时,会提示用户将文件和/或文件夹拖放到应用程序窗口中。

UI: Drop files and.or folders to be counted.

当拖放文件或文件夹时,会调用 Start 方法,更改 UI 元素的可见性以显示计数屏幕。

UI: File and page counts

调用 async Analyze 方法以创建一个新线程,递归地遍历文件系统。将从线程池请求一个新线程,用于枚举每个目录及其文件计数。

private async Task Analyze (IEnumerable<string> filenames)
{
    await Task.Run(async () =>
    {
        foreach (string filename in filenames)
        {
            if (this._cancel)
                break;

            Dispatcher.Invoke(Update);
            if (Directory.Exists(filename))
            {
                string[] nestedFilenames = Directory.GetFiles(filename, "*.pdf", SearchOption.AllDirectories);
                await Analyze(nestedFilenames);
            }

            this._files++;
            if (new FileInfo(filename).Extension.ToLower() != ".pdf")
                continue;

            this._filesPdf++;
            int pages = Count(filename);
            this._pages += pages;
        }
        Dispatcher.Invoke(Update);
    });
}

private int Count (string filename)
{
    using (var reader = new PdfReader(filename))
    {
        int pages = reader.NumberOfPages;
        reader.Close();
        return pages;
    }
}

Count 方法使用了 iTextSharp 库来读取 PDF 文件。由于 PDF 文件内部已建立索引,因此无需扫描文档(请参阅 PDF 语法)。相反,实例化一个 PdfReader 对象并读取其 NumberOfPages 属性。

使用的系统资源可以忽略不计。

Task Manager Performance

PDF 语法

通过创建简单的 PDF 解析器,可以很容易地完成此操作;但是,这将增加开发应用程序所需的时间,而我已经熟悉 iTextSharp,并且开发时间约为一小时。

为了不使用 iTextSharp 完成此操作,我们将读取 PDF 并跟踪引用。

这是一个语法正确且完整的 PDF 文件。要找到该部分,我们首先检查 Trailer,它将引用 1 指定为 Root。我们可以看到部分 1 包含 Catalog,它将引用 3 指向 Pages 部分。请注意,Pages 资源描述了一个页面,该页面在部分 4 中描述。

%PDF-1. 4
1  0  obj
 <<  /Type /Catalog
  /Outlines  2 0 R
  /Pages  3 0 R
 >>
endobj
2  0  obj
 <<  /Type  Outlines
  /Count  0
 >>
endobj
3  0  obj
 <<  /Type  /Pages
  /Kids  [ 4 0 R ]
  /Count  1
 >>
endobj
4  0  obj
 <<  /Type  /Page
  /Parent  3 0 R
  /MediaBox  [ 0  0  612  792 ]
  /Contents  5 0 R
  /Resources  <<  /ProcSet  6 0 R  >>
 >>
endobj
5  0  obj
 <<  /Length  35  >>
 stream
 <-- Page-marking operators -->
 endstream
endobj
6  0  obj
 [ /PDF ]
endobj
xref
0  7
0000000000  65535  f
0000000009  00000  n
0000000074  00000  n
0000000120  00000  n
0000000179  00000  n
0000000300  00000  n
0000000384  00000  n
trailer
 <<  /Size  7
  /Root  1 0 R
 >>
startxref
408
%%EOF

致谢

iTextSharp 是 Paulo Soares、Bruce Lowagie 等人的作品。

PDF 文件语法示例来自 PDF 参考,第六版。© 2006 Adobe®Systems Incorporated。

历史

2014 年 1 月 18 日 应用程序编写完成
2014 年 10 月 24 日 文章编写完成
© . All rights reserved.