2012-04-12 104 views
1

我有很多pdf文档要合并在一起,所以我编写了这个代码来完成它。它适用于只有两个pdf文档需要合并的情况,但如果我给它两个以上的文档,额外的文档就会出现乱码。你能帮我找到问题吗?如何使用PDF :: API2将几个pdf合并为一个Perl?

#!/usr/bin/perl 

use PDF::API2; 
use List::Util qw(reduce); 


# Given two pdfs and a page number, appends the given page of the second pdf to the first pdf 
sub append_page_to_pdf { 
    my ($pdf1, $pdf2, $pg) = @_; 
    $pdf1->importpage($pdf2, $pg); 
} 

# Given two pdfs, appends the second to the first. Closes pdf2 
sub merge_2_pdfs { 
    my ($pdf1, $pdf2) = @_; 
    map &append_page_to_pdf($pdf1, $pdf2, $_), 1..$pdf2->pages; 
    $pdf2->end; 
    return $pdf1; 
} 

# does what it says 
sub open_pdf { 
    my $file = $_[0]; 
    my $pdf = PDF::API2->open($file); 
    print "Opened pdf ($file)\n"; 
    return $pdf; 
} 

# reduces merge_2_pdfs over an array of pdfs 
sub merge_pdfs { 
    my @files = @_; 
    my $starting_filename = shift @files; 
    my $start_pdf = &open_pdf($starting_filename); 
    my $final_pdf = reduce { &merge_2_pdfs($a, &open_pdf($b)) } $start_pdf, @files; 
    return $final_pdf; 
} 

# Get the arguments ie save_name, file1, file2, file3, ... 
my @files = @ARGV; 
my $save_name = shift @files; 
my $save = &merge_pdfs(@files); 
$save->saveas($save_name); 
+1

http://p3rl.org/appendpdf.pl – daxim 2012-04-12 16:47:00

+0

是的,我看到了作为对另一个SO线程的类似问题的回答给出。问题是appendpdf.pl只合并两个pdf文档。我将使用一个使用appendpdf.pl的shell脚本来做到这一点,但这是错误的:没有必要的文件io(一个额外的读写),每个文件都会发生这种情况。 – user787747 2012-04-12 16:52:12

+1

我是appendpdf.pl的作者。这是一个围绕CAM :: PDF的简单包装脚本。附加大量PDF文件是很简单的。看看appendpdf.pl源代码,你会看到。 – 2012-05-05 03:09:57

回答

2

代码中的实际问题是因为您在合并它们之前关闭了其中一个文件。

my $save_name = shift @files; 
# which should be 
my $save_name = $files[0]; 

否则,代码实际上工作,我没有发现任何乱码。

一些提示:

  1. use strictuse warnings

  2. 现在一般的做法是省略你的子程序调用的&。该规则的例外情况为See here

  3. 在这种情况下,子例程会使您的代码变得冗长,这使得难以遵循。这里更简洁一些。

    use strict; 
    use warnings; 
    use List::Util 'reduce'; 
    use PDF::API2; 
    
    my $new 
        = reduce { $a->importpage($b, $_) foreach 1 .. $b->pages; $a } 
        map { PDF::API2->open($_) } 
        @ARGV; 
    $new->saveas('new.pdf'); 
    
  4. 的简单循环是一个小更简单明了比使用reduce阅读。

    use PDF::API2; 
    
    my $new = PDF::API2->new; 
    foreach my $filename (@ARGV) { 
        my $pdf = PDF::API2->open($filename); 
        $new->importpage($pdf, $_) foreach 1 .. $pdf->pages; 
    } 
    $new->saveas('new.pdf'); 
    
+0

真棒回答,男人!我有个问题。为什么&merge_2_pdfs的返回值不会反馈到原始代码的下一个迭代中? – user787747 2012-04-13 13:42:06

+0

我错了。 'merge_2_pdfs()'的返回确实会反馈到下一次迭代中。错误在上面的其他地方。 – stevenl 2012-04-16 04:29:34

1

PDF::Reuse

prFile('myFile.pdf'); 
for my $pdf (@PDFS) { 
    prDoc($pdf); 
} 
prEnd(); 
1

另一种可能是我的图书馆,CAM::PDF

my $pdf1 = CAM::PDF->new($file1) or die; 
my $pdf2 = CAM::PDF->new($file2) or die; 
my $pdf3 = CAM::PDF->new($file3) or die; 
$pdf1->appendPDF($pdf2); 
$pdf1->appendPDF($pdf3); 
$pdf1->cleanoutput($outfile); 

或者将其封装在@ARGV循环中。对于只有两个PDF文件,我有一个简单CMDLINE包装做同样的:

appendpdf.pl file1.pdf file2.pdf out.pdf

相关问题