iText7 Java添加文本问题

用户名

我正在使用iText 7复制pdf页面并为这些页面编号。因此,我不需要手动编号。但是生成的pdf文件中的数字存在问题。看起来是这样的:

发行图片

而且我已经考虑了许多小时,仍然无法弄清楚。

我的代码:

import com.itextpdf.io.font.FontConstants;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;

import java.io.File;
import java.io.IOException;

public class NumberingInJava {

public static final String SRC = "D:/temp/num_src.pdf";
public static final String DEST = "D:/temp/edited_numbering.pdf";

public static final String[] NUM4SAMPLE = {"02A", "03A", "03B", "03C", "04A", "08A"};

public static final double XCOOR = 230;
public static final double YCOOR = 795;//755

public static void main(String[] args) throws IOException {
    File file = new File(DEST);
    file.getParentFile().mkdirs();
    new NumberingInJava().manipulatePdf(SRC, DEST, NUM4SAMPLE);
}

private void manipulatePdf(String src, String dest, String[] numbering4what) throws IOException {

    //Initialize PDF document
    PdfDocument pdfDocToRead = new PdfDocument(new PdfReader(src));
    PdfDocument pdfDocToWrite = new PdfDocument(new PdfWriter(dest));

    for(String s : numbering4what) {
        println(s);
    }

    String number = null;
    PdfPage tempPage = null;
    for (int i=0; i<numbering4what.length; i++) {
        pdfDocToRead.copyPagesTo(1, 2, pdfDocToWrite);
        number = numbering4what[i];
        println(number);
        tempPage = pdfDocToWrite.getPage(2*(i+1)-1);

        numberingPage(tempPage, number);

        println("pdfDocToWrite.numberOfPages : "+pdfDocToWrite.getNumberOfPages());
    }

    pdfDocToRead.close();
    pdfDocToWrite.close();

    println("\nNumber added!");
}

private void numberingPage(PdfPage pdfPage, String number) throws IOException {
    println(pdfPage);
    PdfCanvas canvas = new PdfCanvas(pdfPage);
    canvas.beginText().setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 22)
            .moveText(XCOOR, YCOOR)
            .showText(number)
            .endText();

    println("number: "+number);

}

private void println(Object obj) {
    System.out.println(obj);
}
}

控制台输出:

02A 
03A 
03B 
03C 03A 
04A 
08A 
02A 
com.itextpdf.kernel.pdf.PdfPage@cf768c 
17:58:07,457 | -ch.qos.logback.classic.LoggerContext中的-INFO [默认]-找不到资源[logback.groovy] 
17 ch.qos.logback.classic.LoggerContext中的:58:07,458 | -INFO [默认]-ch.qos.logback.classic.LoggerContext中找不到资源[logback-test.xml] 
17:58:07,458 | -INFO [默认]-在[jar:file:/ D:/Java_Packages/ext_lib/iText/itext7-7.0.1/itext7-itext-rups-7.0.1.jar!/logback.xml]中找到资源[logback.xml] 
17:58:07,459 | -WARN在ch.qos.logback.classic.LoggerContext中[默认]-资源[logback.xml]在类路径上多次出现。
17:58:07,459 | -ch.qos.logback.classic.LoggerContext中的[默认]-资源[logback.xml]出现在[jar:file:/ D:/Java_Packages/ext_lib/iText/itext7-7.0.1 /itext7-itext-rups-7.0.1-jar-with-dependencies.jar!/logback.xml] 
17:58:07,459 | -ch.qos.logback.classic.LoggerContext中的WARN [默认]-资源[logback。 xml]发生在[jar:file:/ D:/Java_Packages/ext_lib/iText/itext7-7.0.1/itext7-itext-rups-7.0.1-sources.jar!/logback.xml] 
17:58:07,459 | ch.qos.logback.classic.LoggerContext中的-WARN [默认]-资源[logback.xml]出现在[jar:file:/ D:/Java_Packages/ext_lib/iText/itext7-7.0.1/itext7-itext-rups -7.0.1.jar!/logback.xml]
ch.qos.logback.core.joran.spi.ConfigurationWatchList@8080bb中的17:58:07,501 | -INFO-URL [jar:file:/ D:/Java_Packages/ext_lib/iText/itext7-7.0.1/itext7-itext ch.qos.logback.core.joran.action.AppenderAction中的-rups-7.0.1.jar!/logback.xml]不是文件类型
17:58:07,662 | -INFO在ch.qos.logback.classic.joran.action.ConfigurationAction中-未设置调试属性
17:58:07,829 | -INFO .itextpdf.rups.view.DebugAppender] 
17:58:07,851 | -INFO在ch.qos.logback.core.joran.action.AppenderAction中-将追加程序命名为[DEFAULT_APP] 
17:58:07,940 | -INFO在ch.qos中.logback.core.joran.action.NestedComplexPropertyIA-假设[encoder]属性的默认类型为[ch.qos.logback.classic.encoder.PatternLayoutEncoder]属性
17:58:08,045 | -INFO在ch.qos.logback.core.joran中.action.AppenderAction-关于实例化类型为[com.itextpdf.rups.view.StyleAppender]的附加程序 
17:58:08,046 | -ch.qos.logback.core.joran.action.AppenderAction中的-INFO-将追加程序命名为[INFO_APP] 
17:58:08,062 | -INFO在ch.qos.logback.core.joran.action.NestedComplexPropertyIA中-假设[encoder]属性的默认类型为[ch.qos.logback.classic.encoder.PatternLayoutEncoder]
ch.qos.logback.core.joran.action.AppenderAction中的17:58:08,063 | -INFO |即将实例化[com.itextpdf.rups.view.DebugAppender]类型的附加程序
17:58:08,063 | -ch中的-INFO .qos.logback.core.joran.action.AppenderAction-在ch.qos.logback.core.joran.action.NestedComplexPropertyIA中将附加程序命名为[DEBUG_APP] 
17:58:08,065 | -INFO-假定默认类型为[ch.qos。用于[encoder]属性的logback.classic.encoder.PatternLayoutEncoder]  
17:58:08,066 | -INFO在ch.qos.logback.core.joran.action.AppenderAction中-关于实例化类型[com.itextpdf.rups.view.DebugAppender]的附加程序
17:58:08,066 | -ch.qos.logback.core.joran.action.AppenderAction中的-INFO-将追加程序命名为[TRACE_APP] 
17:58:08,067 | -INFO在ch.qos.logback.core.joran.action.NestedComplexPropertyIA中-假设[encoder]属性的默认类型为[ch.qos.logback.classic.encoder.PatternLayoutEncoder] 
17:58:08,069 | -INFO在ch.qos.logback.core.joran.action中。 AppenderAction-要实例化[com.itextpdf.rups.view.StyleAppender]类型的追加程序
17:58:08,069 | -ch.qos.logback.core.joran.action.AppenderAction中的-INFO-将追加程序命名为[IMPORTANT_APP] 
17: ch.qos.logback.core.joran.action.NestedComplexPropertyIA中的58:08,075 | -INFO |假设[encoder]属性的默认类型为[ch.qos.logback.classic.encoder.PatternLayoutEncoder] 
17:58:08,076 | -INFO在ch.qos.logback.classic.joran.action.LoggerAction中-将记录器[com.itextpdf]的可加性设置为false
ch.qos.logback.core.joran.action.AppenderRefAction中的17:58:08,077 | -INFO-将名为[IMPORTANT_APP]的附加程序附加到Logger [com.itextpdf]
ch.qos.logback.classic.joran.action.ConfigurationAction中的 17:58:08,078 | -INFO中-配置结束。 
17 :58:08,078 | -ch.qos.logback.core.joran.action.AppenderRefAction中的INFO-将名为[INFO_APP]的附加程序附加到Logger [com.itextpdf]
ch.qos.logback.core.joran.action.AppenderRefAction中的17:58:08,078 | -INFO |将名为[DEBUG_APP]的附加程序附加到Logger [com.itextpdf] 
17:58:08,078 | -INFO中ch.qos.logback .core.joran.action.AppenderRefAction-将名为[TRACE_APP]的附加程序附加到Logger [com.itextpdf] 
17:58:08,078 | -ch.qos.logback.classic.joran.action.RootLoggerAction中的-INFO-设置ROOT记录器的级别到TRACE 
17:58:08,078 | -ch.qos.logback.core.joran.action.AppenderRefAction中的信息-将名为[DEFAULT_APP]的附加程序附加到Logger [ROOT] 
17:58:08,082 | ch.qos.logback中的-INFO .classic.joran.JoranConfigurator @ 1c24521-将当前配置注册为安全的回退点

数:02A pdfDocToWrite.numberOfPages:2 03A com.itextpdf.kernel.pdf.PdfPage@11aa95a 号:03A pdfDocToWrite.numberOfPages:4 03B com.itextpdf.kernel.pdf.PdfPage@bc05a6 数:03B pdfDocToWrite.numberOfPages:6 03C COM .itextpdf.kernel.pdf.PdfPage @ ef309d 数:03C pdfDocToWrite.numberOfPages:8 04A com.itextpdf.kernel.pdf.PdfPage@1fc609f 数:04A pdfDocToWrite.numberOfPages:10 08A com.itextpdf.kernel.pdf.PdfPage@173813a 编号:08A pdfDocToWrite.numberOfPages:12

已添加号码!

流程结束,退出代码为0

编辑:我已经在Dropbox上上传了一个模拟文档和一个已编辑文档,这里是:模拟文档

编辑的模拟文档

mkl

原因

该问题是由于iText试图使结果PDF变小而引起的:

当您将pdfDocToRead多个页面复制到时pdfDocToWrite,实际的页面内容流,页面资源等仅被复制一次,对于每个副本和页面,仅生成一个引用这些数据的小对象一次。

这种优化还不是问题,但进一步的微观优化是,

PdfCanvas canvas = new PdfCanvas(pdfPage);

PdfCanvas帮助程序方法用于检索将添加内容的内容流:

private static PdfStream getPageStream(PdfPage page) {
    PdfStream stream = page.getContentStream(page.getContentStreamCount() - 1);
    return stream == null || stream.getOutputStream() == null || stream.containsKey(PdfName.Filter) ? page.newContentStreamAfter() : stream;
}

如您所见,通常会在页面(page.newContentStreamAfter())中添加新的内容流仅当已经有内容流并且该流没有过滤器(例如用于压缩)时,才使用此现有内容流向其追加数据。

对于您的文档,不会压缩为每个源页面复制的单个内容流。因此,这两个优化导致您的所有PdfCanvas canvas实例附加到同一单个内容流。

解决方法

显而易见的解决方法是规避后者的优化:替换行

PdfCanvas canvas = new PdfCanvas(pdfPage);

经过

PdfCanvas canvas = new PdfCanvas(pdfPage.newContentStreamAfter(), pdfPage.getResources(), pdfPage.getDocument());

(在StampPageNumbers.java方法中numberingPage

本质上,如果原始内容流被压缩,也将发生这种情况。

(通常,实际上可能必须先在当前内容之前使用save-graphics-state指令添加一个新的内容流,并在当前内容之后最初向新的内容流添加一个restore-graphics-state指令;对于您的示例文档,但是,这不是必需的,因为当前状态不会不利地改变图形状态。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用itext7的addind文本

来自分类Dev

iText7 - 在表格问题中显示文本

来自分类Dev

如何使用itext7从标记的pdf中的结构元素中提取文本

来自分类Dev

我如何使用itext7从存储在Blob存储中的pdf中提取文本?

来自分类Dev

在iText7(.NET)中将页脚添加到现有PDF的每一页

来自分类Dev

itext7 中可以避免添加 xmp:ModifyDate 吗?

来自分类Dev

使用 IText7 将 SVG 图像添加到 PDF

来自分类Dev

在itext7中,如何按添加时间更改附件显示顺序

来自分类Dev

itext7 java.lang.NoClassDefFoundError: org.bouncycastle.asn1.esf.SignaturePolicyIdentifier

来自分类Dev

iText7 目录

来自分类Dev

在带有iText7的页面上移动文本,保留字体,颜色,样式等,但更改文本的大小

来自分类Dev

如何使用带有 C# 的 itext7 将 u3d 添加到现有的 pdf 中

来自分类Dev

iText7以错误的顺序读出行

来自分类Dev

iText7(.net)SignExternalSignatureContainer NullReferenceException

来自分类Dev

在IText7中创建PdfFont

来自分类Dev

iText7 - 如何设置 LoggerFactory?

来自分类Dev

iText7 无法设置日志

来自分类Dev

Itext7 pdf.version.not.valid

来自分类Dev

iText7 setRotation() 无法正常工作

来自分类Dev

iText7 图像透明度

来自分类Dev

itext 7表边框问题

来自分类Dev

iText 7添加彩色文本并填充到矩形

来自分类Dev

iText 7添加彩色文本并填充到矩形

来自分类Dev

在iText7中的jar中提供字体

来自分类Dev

IText7和C#中缺少GetPageN方法

来自分类Dev

iText7:如何获取段落的实际宽度

来自分类Dev

用iText7填充pdf检查字段

来自分类Dev

什么可以替代itext7中的短语?

来自分类Dev

iText7数字签名图像对齐