教你怎么用Java通過關(guān)鍵字修改pdf
一、前言
在main方法中測試該方法,還需要引用的jar包有itextpdf-5.5.10.jar、itext-asian-5.2.0.jar
注意:兩jar包之間有版本對(duì)應(yīng),否則會(huì)出現(xiàn)報(bào)錯(cuò),該報(bào)錯(cuò)主要針對(duì)設(shè)置中文字體的方法
java itext 報(bào)錯(cuò) com.itextpdf.text.DocumentException: Font 'STSong-Light' with 'UniGB-UCS2-H'
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
/**
* @Desc
* @Author madengling
* @Time 2021/5/11 15:18
*/
public class UpdatePdf {
public static void main(String[] args) {
File file = new File("G://files//cs//111.pdf");//模擬文件位置
if(file!=null && file.exists()){
FileInputStream is = null;
try {
//本地根據(jù)文件路徑獲取文件流
is = new FileInputStream(file);
long length = file.length();
byte[] fileBytes = new byte[(int)length];
is.read(fileBytes);
//進(jìn)行pdf文件修改
File file1 = pdfFzSqsj(fileBytes);
if(file1!=null && file1.exists()){
System.out.println("修改pdf完成!");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 根據(jù)pdf的固定關(guān)鍵字,查找進(jìn)行pdf相關(guān)位置增加文字
* @param tpeHtcxyw 文件流
* @return 修改后的文件
*/
private static File pdfFzSqsj(byte[] tpeHtcxyw) {
PdfStamper stamper = null;
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
//獲取要寫入的申請(qǐng)時(shí)間
String sj =sdf.format(new Date());
PdfReader reader = new PdfReader(tpeHtcxyw);
//創(chuàng)建文件路徑
String filePath = "G://files/cs/";
System.out.println("filePath="+filePath);
File directory = new File(filePath);
//如果pdf保存路徑不存在,則創(chuàng)建路徑
if (!directory.exists()) {
directory.mkdirs();
}
String filename = UUID.randomUUID()+"_after.pdf";//修改后文件
String filename1 = UUID.randomUUID()+"_before.pdf";//修改前文件 再輸出一遍,校驗(yàn)自己在修改之前拿到正確的文件流
System.out.println("file:"+filePath+filename);
File file = new File(filePath+filename);
File file1 = new File(filePath+filename1);
//將寫入臨時(shí)文件
FileOutputStream foss = new FileOutputStream (file1);
foss.write(tpeHtcxyw);
foss.close();
//設(shè)置字體
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
Font font = new Font(baseFont);
stamper = new PdfStamper(reader, new FileOutputStream(file));
//對(duì)于已經(jīng)固話的pdf回填申請(qǐng)時(shí)間
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfContentByte over = stamper.getOverContent(i);
ColumnText columnText = new ColumnText(over);
if(i==1){
String str = "申請(qǐng)日期:";
//根據(jù)關(guān)鍵字獲取關(guān)鍵字位置
float[] po = Html2Pdf.getGzzzb(str,tpeHtcxyw);
if(po[0]==1.00f){
// 方法setSimpleColumn(float llx, float lly, float urx, float ury)
// llx 和 urx 最小的值決定離左邊的距離. lly 和 ury 最大的值決定離下邊的距離
columnText.setSimpleColumn( po[1]+46f, po[2]-9f, 500, 0);
//將時(shí)間文本創(chuàng)建成對(duì)象
Paragraph elements = new Paragraph(0, new Chunk(new Chunk(sj)));
// 設(shè)置字體,如果不設(shè)置添加的中文將無法顯示
elements.setFont(font);
columnText.addElement(elements);
columnText.go();
}
}
}
return file;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(stamper!=null){
try {
stamper.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
二、Html2Pdf
import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
public class Html2Pdf {
/**
* 定位pdf文件中關(guān)鍵字坐標(biāo)
* @param signKey 關(guān)鍵字
* @param pdf 文件流
* @return 坐標(biāo)位置
*/
public static float[] getGzzzb(String signKey, byte[] pdf){
PdfReader reader=null;
final float[] po = new float[3];
try{
reader = new PdfReader(pdf);
int pageNum = reader.getNumberOfPages();
final String signKeyWord = signKey;
for(int page=1; page <= pageNum; page++){
PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(reader);
pdfReaderContentParser.processContent(page, new RenderListener() {
StringBuilder sb = new StringBuilder("");
int maxLength = signKeyWord.length();
@Override
public void renderText(TextRenderInfo textRenderInfo) {
// 只適用 單字塊文檔 以及 關(guān)鍵字整個(gè)為一個(gè)塊的情況
// 設(shè)置 關(guān)鍵字文本為單獨(dú)的塊,不然會(huì)錯(cuò)位
boolean isKeywordChunk = textRenderInfo.getText().length() == maxLength;
if (isKeywordChunk) {
// 文檔按照 塊 讀取
sb.delete(0, sb.length());
sb.append(textRenderInfo.getText());
} else {
// 有些文檔 單字一個(gè)塊的情況
// 拼接字符串
sb.append(textRenderInfo.getText());
// 去除首部字符串,使長度等于關(guān)鍵字長度
if (sb.length() > maxLength) {
sb.delete(0, sb.length() - maxLength);
}
}
// 判斷是否匹配上
if (signKeyWord.equals(sb.toString())) {
// 計(jì)算中心點(diǎn)坐標(biāo)
Rectangle2D.Float baseFloat = textRenderInfo.getBaseline()
.getBoundingRectange();
Rectangle2D.Float ascentFloat = textRenderInfo.getAscentLine()
.getBoundingRectange();
float centreX;
float centreY;
if (isKeywordChunk) {
centreX = baseFloat.x + 5*ascentFloat.width / 6;
centreY = baseFloat.y + (5*(ascentFloat.y - baseFloat.y) / 6);
} else {
centreX = baseFloat.x + ascentFloat.width - (5*maxLength * ascentFloat.width / 6);
centreY = baseFloat.y + (5*(ascentFloat.y - baseFloat.y) / 6);
}
po[0]=1.00f;
po[1]=centreX+3;
po[2]=centreY;
// 匹配完后 清除
sb.delete(0, sb.length());
}
}
@Override
public void renderImage(ImageRenderInfo arg0) {}
@Override
public void endTextBlock() {}
@Override
public void beginTextBlock() {}
});
}
if(po[0]==1.00f){
return po;
}
}catch(Exception e){
e.printStackTrace();
}finally {
if(reader!=null){
reader.close();
}
}
return null;
}
三、結(jié)果圖
111.pdf是原始文件,其余兩文件在方法執(zhí)行后生成,before文件內(nèi)容與111.pdf一致

我的原始pdf中含有關(guān)鍵字申請(qǐng)時(shí)間,修改前后文件內(nèi)容如下:


到此這篇關(guān)于教你怎么用Java通過關(guān)鍵字修改pdf的文章就介紹到這了,更多相關(guān)關(guān)鍵字修改pdf內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java 使用openoffice進(jìn)行word轉(zhuǎn)換為pdf的方法步驟
- Java使用iTextPDF生成PDF文件的實(shí)現(xiàn)方法
- Java 實(shí)現(xiàn)word模板轉(zhuǎn)為pdf
- java 后端生成pdf模板合并單元格表格的案例
- java 畫pdf用itext調(diào)整表格寬度、自定義各個(gè)列寬的方法
- java 用itext設(shè)置pdf紙張大小操作
- Java生成pdf文件或jpg圖片的案例講解
- 用Java驗(yàn)證pdf文件的電子章簽名
- 基于Java SWFTools實(shí)現(xiàn)把pdf轉(zhuǎn)成swf
- Java實(shí)現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的示例
- Java pdf和jpg互轉(zhuǎn)案例
- Java實(shí)現(xiàn)圖片轉(zhuǎn)換PDF文件的示例代碼
- Java 基于Spire.Cloud.SDK for Java在PDF中繪制形狀
- Java 在PDF中添加騎縫章示例解析
- Java 在PDF中繪制形狀的兩種方法
相關(guān)文章
Java中ThreadLocal避免內(nèi)存泄漏的方法詳解
ThreadLocal是Java中的一個(gè)線程本地存儲(chǔ)機(jī)制,它允許每個(gè)線程擁有一個(gè)獨(dú)立的本地存儲(chǔ)空間,用于存儲(chǔ)該線程的變量,本文主要介紹了ThreadLocal如何避免內(nèi)存泄漏,需要的朋友可以參考下2023-05-05
java異常繼承何類,運(yùn)行時(shí)異常與一般異常的區(qū)別(詳解)
下面小編就為大家?guī)硪黄猨ava異常繼承何類,運(yùn)行時(shí)異常與一般異常的區(qū)別(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11
SpringBoot遇到的坑@Qualifier報(bào)紅的解決
這篇文章主要介紹了SpringBoot遇到的坑@Qualifier報(bào)紅的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Spring?Boot請(qǐng)求處理之常用參數(shù)注解使用教程
這篇文章主要給大家介紹了關(guān)于Spring?Boot請(qǐng)求處理之常用參數(shù)注解使用的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03
Java 實(shí)現(xiàn)Excel文檔添加超鏈接的代碼
超鏈接即內(nèi)容鏈接,通過給特定對(duì)象設(shè)置超鏈接,可實(shí)現(xiàn)載體與特定網(wǎng)頁、文件、郵件、網(wǎng)絡(luò)等的鏈接,點(diǎn)擊鏈接載體可打開鏈接目標(biāo),在文檔處理中是一種比較常用的功能,本文將介紹通過Java程序給Excel文檔添加超鏈接的方法,感興趣的朋友一起看看吧2020-02-02

