如何重新排列 PDF 文件的页面?
How to reorder the pages of a PDF file?
我终于生成了 Table 个内容,我想在开头移动 Table 个内容。
假设我的 PDF 中有 16 页,目录从第 13 页开始到第 15 页结束。
我想将 TOC 移动到第二页,以便第一页保留为第 1 页,最后一页保留为第 16 页。
此代码没有提供我想要的内容:
public void changePagesOrder() {
try {
PdfReader sourcePDFReader = new PdfReader(RESULT1);
int n = sourcePDFReader.getNumberOfPages();
System.out.println("no of pages in pdf files..."+n);
int totalNoPages=n;
int tocStartsPage=13;
sourcePDFReader.selectPages(String.format("%d-%d, 2-%d", tocStartsPage, totalNoPages-1, tocStartsPage -2));
PdfStamper stamper = new PdfStamper(sourcePDFReader, new FileOutputStream(RESULT2));
stamper.close();
System.out.println("pdf changes are done.....");
}
catch(Exception ex) {
}
}
请提出一些解决方案。
您可以select PdfReader阅读的页面:
PdfReader sourcePDFReader = new PdfReader(RESULT1);
reader.selectPages("1-13");
然后你可以使用 PdfStamper 或 PdfCopy 到 assemble 然后按顺序。
请参考:
Itext Documentation, Related question
编辑: 这是我用来将 pdf 列表放在一起的一段代码,也许对您有帮助。 (您可以阅读第 15-16 页,保存为 pdf,然后重复第 1-13 页。然后合并两个生成的 pdf)
private byte[] combinePdf(List<byte[]> archivos) throws DocumentException,
IOException {
ByteArrayOutputStream osPdf = new ByteArrayOutputStream();
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter writer = PdfWriter.getInstance(document, osPdf);
document.open();
PdfContentByte cb = writer.getDirectContent();
for (byte[] in : archivos) {
PdfReader reader = new PdfReader(in);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
cb.addTemplate(page, 0, 0);
}
}
osPdf.flush();
document.close();
return osPdf.toByteArray();
}
编辑 2: 正如 Bruno 发布的那样,这是一个糟糕的解决方案,因为使用 document/pdfWritter 组合会丢失所有 pdf 链接。
你的公式有误。你有:
sourcePDFReader.selectPages(String.format("%d-%d, 2-%d", tocStartsPage, totalNoPages-1, tocStartsPage -2);
但这会将您的目录放在第 1 页。根据您的描述,这不是您想要的。
你想要这样的东西:
PdfReader reader = new PdfReader(baos.toByteArray());
int startToc = 13;
int n = reader.getNumberOfPages();
reader.selectPages(String.format("1,%s-%s, 2-%s, %s", startToc, n-1, startToc - 1, n));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.close();
此代码已使用 ReorderPage example on a PDF with 16 pages, having the text Page 1
, Page 2
, ..., Page 16
as content. The result was the following PDF: (reordered.pdf)[http://itextpdf.com/sites/default/files/reordered.pdf]
进行测试
页面现在的顺序是:第 1 页、第 13 页、第 14 页、第 15 页、第 2 页、第 3 页、第 4 页、第 5 页、第 6 页、第 7 页、第 8 页、第 9 页、第10、第 11 页、第 12 页、第 16 页。这是您在问题中描述的顺序。
更新:
在评论中,您询问 String.format()
在这种情况下是如何工作的。
让我们先看看我们想要实现什么。我们的页面顺序如下:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
我们想像这样重新排序:
1, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16
这意味着我们需要这个模式:
1, 13-15, 2-12, 16
这是一个硬编码模式,其中两个变量很重要:
- 目录开头:第 13 页(
startToc
)
- 最后一页:16 (
n
)
从这些变量中,我们推导出另外两个变量:
- 目录的最后一页。这是最后一页减去一页,即 16 - 1 = 15 (
n - 1
)
- TOC 之前的最后一页:13 - 1 = 12 (
startToc - 1
)
我们现在可以像这样重写模式:
1, startToc-(n - 1), 2-(startToc - 1), n
我们需要将其设为 String
,因此我们使用 String.format()
:
String.format("1,%s-%s, 2-%s, %s", startToc, n-1, startToc - 1, n)
第一次出现的%s
被String
后的第一个参数代替,第二次出现的%s
被String
后的第二个参数代替,等等...
如果 startToc = 13
和 n = 16
,结果为:
1, 13-15, 2-12, 16
我终于生成了 Table 个内容,我想在开头移动 Table 个内容。 假设我的 PDF 中有 16 页,目录从第 13 页开始到第 15 页结束。 我想将 TOC 移动到第二页,以便第一页保留为第 1 页,最后一页保留为第 16 页。 此代码没有提供我想要的内容:
public void changePagesOrder() {
try {
PdfReader sourcePDFReader = new PdfReader(RESULT1);
int n = sourcePDFReader.getNumberOfPages();
System.out.println("no of pages in pdf files..."+n);
int totalNoPages=n;
int tocStartsPage=13;
sourcePDFReader.selectPages(String.format("%d-%d, 2-%d", tocStartsPage, totalNoPages-1, tocStartsPage -2));
PdfStamper stamper = new PdfStamper(sourcePDFReader, new FileOutputStream(RESULT2));
stamper.close();
System.out.println("pdf changes are done.....");
}
catch(Exception ex) {
}
}
请提出一些解决方案。
您可以select PdfReader阅读的页面:
PdfReader sourcePDFReader = new PdfReader(RESULT1);
reader.selectPages("1-13");
然后你可以使用 PdfStamper 或 PdfCopy 到 assemble 然后按顺序。 请参考:
Itext Documentation, Related question
编辑: 这是我用来将 pdf 列表放在一起的一段代码,也许对您有帮助。 (您可以阅读第 15-16 页,保存为 pdf,然后重复第 1-13 页。然后合并两个生成的 pdf)
private byte[] combinePdf(List<byte[]> archivos) throws DocumentException,
IOException {
ByteArrayOutputStream osPdf = new ByteArrayOutputStream();
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter writer = PdfWriter.getInstance(document, osPdf);
document.open();
PdfContentByte cb = writer.getDirectContent();
for (byte[] in : archivos) {
PdfReader reader = new PdfReader(in);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
cb.addTemplate(page, 0, 0);
}
}
osPdf.flush();
document.close();
return osPdf.toByteArray();
}
编辑 2: 正如 Bruno 发布的那样,这是一个糟糕的解决方案,因为使用 document/pdfWritter 组合会丢失所有 pdf 链接。
你的公式有误。你有:
sourcePDFReader.selectPages(String.format("%d-%d, 2-%d", tocStartsPage, totalNoPages-1, tocStartsPage -2);
但这会将您的目录放在第 1 页。根据您的描述,这不是您想要的。
你想要这样的东西:
PdfReader reader = new PdfReader(baos.toByteArray());
int startToc = 13;
int n = reader.getNumberOfPages();
reader.selectPages(String.format("1,%s-%s, 2-%s, %s", startToc, n-1, startToc - 1, n));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.close();
此代码已使用 ReorderPage example on a PDF with 16 pages, having the text Page 1
, Page 2
, ..., Page 16
as content. The result was the following PDF: (reordered.pdf)[http://itextpdf.com/sites/default/files/reordered.pdf]
页面现在的顺序是:第 1 页、第 13 页、第 14 页、第 15 页、第 2 页、第 3 页、第 4 页、第 5 页、第 6 页、第 7 页、第 8 页、第 9 页、第10、第 11 页、第 12 页、第 16 页。这是您在问题中描述的顺序。
更新:
在评论中,您询问 String.format()
在这种情况下是如何工作的。
让我们先看看我们想要实现什么。我们的页面顺序如下:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
我们想像这样重新排序:
1, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16
这意味着我们需要这个模式:
1, 13-15, 2-12, 16
这是一个硬编码模式,其中两个变量很重要:
- 目录开头:第 13 页(
startToc
) - 最后一页:16 (
n
)
从这些变量中,我们推导出另外两个变量:
- 目录的最后一页。这是最后一页减去一页,即 16 - 1 = 15 (
n - 1
) - TOC 之前的最后一页:13 - 1 = 12 (
startToc - 1
)
我们现在可以像这样重写模式:
1, startToc-(n - 1), 2-(startToc - 1), n
我们需要将其设为 String
,因此我们使用 String.format()
:
String.format("1,%s-%s, 2-%s, %s", startToc, n-1, startToc - 1, n)
第一次出现的%s
被String
后的第一个参数代替,第二次出现的%s
被String
后的第二个参数代替,等等...
如果 startToc = 13
和 n = 16
,结果为:
1, 13-15, 2-12, 16