java使用itex讀取pdf,並搜索關鍵字,為其蓋章


導讀:近期要做一個根據關鍵字定位pdf的蓋章位置的相關需求,其中關鍵字可配置多個(包含pdf文檔中可能不存在的關鍵字),當頁面顯示蓋章完成時,打開pdf顯示已經損壞。 
排查后發現,當itext搜索的關鍵字在pdf文檔中不存在時,就已經將結果返回到前台界面,這時itex讀取的流還未關閉,導致pdf讀取未結束,pdf文檔才被損壞。 
下面是讀取pdf的操作,記錄一下: 
所需包: itext-2.06.jar itext-asian,jar itextpdf-5.4.0.jar

 

 /****搜索關鍵字操作:****/
   /*sourcePDF: pdf的文檔路徑
   splitParentkeyValues[i]:關鍵字,其中對關鍵字進行特殊符號的過濾,不然會導致后面的匹配結果有誤。*/
   matches = MatchItemUtil.matchPage(sourcePDF, splitParentkeyValues[i]);
 
 /*找出關鍵字后,將要蓋章的圖片准確定位到關鍵字周圍,也可以采用坐標的方式**/
 MatchItem matchItem  = new MatchItem();
 int pageNum = matches.get(j).getPageNum();
 float pageWidth = reader.getPageSize(pageNum).getWidth();
 float pageHeight = reader.getPageSize(pageNum).getHeight();
 matchItem.setX(matches.get(j).getX()-splitParentkeyValues.length * 20);
 matchItem.setY(matches.get(j).getY() - 150 / 1.527731f);
 img.setAbsolutePosition(matchItem.getX(), matchItem.getY());// 位置
 PdfContentByte over = stamp.getOverContent(pageNum);
 over.addImage(img);

1. //根據關鍵字和pdf路徑,全文搜索關鍵字 

 /**
 
 查找所有
 @param fileName 文件路徑
 @param keyword 關鍵詞
 @return
 @throws Exception 
 */
 public static List matchPage(String fileName,String keyword) throws Exception { 
 List items = new ArrayList(); 
 PdfReader reader = new PdfReader(fileName); 
 int pageSize = reader.getNumberOfPages(); 
 for(int page = 1;page <= pageSize;page++){ 
 items.addAll(matchPage(reader,page,keyword)); 
 } 
 return items; 
 }

2. 根據關鍵字、文檔路徑、pdf頁數尋找特定的文件內容

 /**
 
 在文件中尋找特定的文字內容
 @param reader
 @param pageNumber
 @param keyword
 @return
 @throws Exception 
 */ 
 public static List matchPage(PdfReader reader, Integer pageNumber,String keyword) throws Exception { 
 KeyWordPositionListener renderListener = new KeyWordPositionListener(); 
 renderListener.setKeyword(keyword); 
 PdfReaderContentParser parse = new PdfReaderContentParser(reader); 
 Rectangle rectangle = reader.getPageSize(pageNumber); 
 renderListener.setPageNumber(pageNumber); 
 renderListener.setCurPageSize(rectangle); 
 parse.processContent(pageNumber, renderListener); 
 return findKeywordItems(renderListener,keyword); 
 }

3. 找到匹配的關鍵詞塊 

/**

找到匹配的關鍵詞塊
@param renderListener
@param keyword
@return 
*/ 
public static List findKeywordItems(KeyWordPositionListener renderListener,String keyword){ 
//先判斷本頁中是否存在關鍵詞 
List allItems = renderListener.getAllItems();//所有塊LIST 
StringBuffer sbtemp = new StringBuffer(“”); 
for(MatchItem item : allItems){//將一頁中所有的塊內容連接起來組成一個字符串。 
sbtemp.append(item.getContent()); 
} 
if(sbtemp.toString().indexOf(keyword) == -1){//一頁組成的字符串沒有關鍵詞,直接return 
return renderListener.getMatches(); 
} 
//第一種情況:關鍵詞與塊內容完全匹配的項 
List matches = renderListener.getMatches(); 
//第二種情況:多個塊內容拼成一個關鍵詞,則一個一個來匹配,組裝成一個關鍵詞 
sbtemp = new StringBuffer(“”); 
List tempItems = new ArrayList(); 
for(MatchItem item : allItems){ 
//1,關鍵詞中存在某塊 2,拼裝的連續的塊=關鍵詞 3,避開某個塊完全匹配關鍵詞 
//關鍵詞 中國移動 而塊為 中 ,國,移動 
//關鍵詞 中華人民 而塊為中,華人民共和國 這種情況解決不了,也不允許存在 
if(keyword.indexOf(item.getContent()) != -1 && !keyword.equals(item.getContent())){ 
tempItems.add(item); 
sbtemp.append(item.getContent()); 
if(keyword.indexOf(sbtemp.toString()) == -1){//如果暫存的字符串和關鍵詞 不再匹配時 
sbtemp = new StringBuffer(item.getContent()); 
tempItems.clear(); 
tempItems.add(item); 
} 
if(sbtemp.toString().equalsIgnoreCase(keyword)){//暫存的字符串正好匹配到關鍵詞時 
MatchItem tmpitem = getRightItem(tempItems, keyword); 
if(tmpitem != null){ 
matches.add(tmpitem);//得到匹配的項 
} 
sbtemp = new StringBuffer(“”);//清空暫存的字符串 
tempItems.clear();//清空暫存的LIST 
continue;//繼續查找 
} 
}else{//如果找不到則清空 
sbtemp = new StringBuffer(“”); 
tempItems.clear(); 
} 
} 
//第三種情況:關鍵詞存在塊中 
for(MatchItem item : allItems){ 
if(item.getContent().indexOf(keyword) != -1 && !keyword.equals(item.getContent())){ 
matches.add(item); 
} 
} 
return matches; 
}

public static MatchItem getRightItem(List<MatchItem> tempItems,String keyword){ 
for(MatchItem item:tempItems){ 
    if(keyword.indexOf(item.getContent()) != -1 && !keyword.equals(item.getContent())){ 
      return item; 
    } 
  } return null; 
}
 
         
4. KeyWordPositionListener用來匹配pdf的關鍵詞
import java.util.ArrayList; 
import java.util.List;

import org.apache.log4j.Logger; 
import org.drools.util.StringUtils;

import com.itextpdf.awt.geom.Rectangle2D; 
import com.itextpdf.text.Rectangle; 
import com.itextpdf.text.pdf.parser.ImageRenderInfo; 
import com.itextpdf.text.pdf.parser.RenderListener; 
import com.itextpdf.text.pdf.parser.TextRenderInfo; 
public class KeyWordPositionListener implements RenderListener { 
private static Logger logger = Logger.getLogger(KeyWordPositionListener.class);
private List<MatchItem> matches = new ArrayList<MatchItem>();
private List<MatchItem> allItems = new ArrayList<MatchItem>();
private Rectangle curPageSize;

/**
 * 匹配的關鍵字
 */
private String keyword;
/**
 * 匹配的當前頁
 */
private Integer pageNumber;

public void beginTextBlock() {
    //do nothing
}

public void renderText(TextRenderInfo renderInfo) {
    String content = renderInfo.getText();
    content = content.replace("<", "").replace("《", "").replace("(", "").replace("(", "").replace("\"", "").replace("'", "")
                     .replace(">", "").replace("》", "").replace(")", "").replace(")", "").replace("、", "").replace(".", "")
                     .replace(":", "").replace(":", "").replace(" ", "");
    Rectangle2D.Float textRectangle = renderInfo.getDescentLine().getBoundingRectange();
    MatchItem item = new MatchItem();
    item.setContent(content);
    item.setPageNum(pageNumber);
    item.setPageWidth(curPageSize.getWidth());
    item.setPageHeight(curPageSize.getHeight());
    item.setX((float)textRectangle.getX());
    item.setY((float)textRectangle.getY());
    if(!StringUtils.isEmpty(content)){
        if(content.equalsIgnoreCase(keyword)) {
            matches.add(item);
        }           
    }else{
        item.setContent("空字符串");
    }
    allItems.add(item);//先保存所有的項
}

public void endTextBlock() {
    //do nothing
}

public void renderImage(ImageRenderInfo renderInfo) {
    //do nothing
}

/**
 * 設置需要匹配的當前頁
 * @param pageNumber
 */
public void setPageNumber(Integer pageNumber) {
    this.pageNumber = pageNumber;
}

/**
 * 設置需要匹配的關鍵字,忽略大小寫
 * @param keyword
 */
public void setKeyword(String keyword) {
    this.keyword = keyword;
}

/**
 * 返回匹配的結果列表
 * @return
 */
public List<MatchItem> getMatches() {
    return matches;
}

void setCurPageSize(Rectangle rect) {
    this.curPageSize = rect;
}

public List<MatchItem> getAllItems() {
    return allItems;
}

public void setAllItems(List<MatchItem> allItems) {
    this.allItems = allItems;
}
}

5. 用來保存關鍵字新建的對象 

public class MatchItem { 
private Integer pageNum; 
private Float x; 
private Float y; 
private Float pageWidth; 
private Float pageHeight; 
private String content;
public Integer getPageNum() {
    return pageNum;
}
public void setPageNum(Integer pageNum) {
    this.pageNum = pageNum;
}
public Float getX() {
    return x;
}
public void setX(Float x) {
    this.x = x;
}
public Float getY() {
    return y;
}
public void setY(Float y) {
    this.y = y;
}
public Float getPageWidth() {
    return pageWidth;
}
public void setPageWidth(Float pageWidth) {
    this.pageWidth = pageWidth;
}
public Float getPageHeight() {
    return pageHeight;
}
public void setPageHeight(Float pageHeight) {
    this.pageHeight = pageHeight;
}
public String getContent() {
    return content;
}
public void setContent(String content) {
    this.content = content;
}

public String toString() {
    return "MatchItem [pageNum=" + pageNum + ", x=" + x + ", y=" + y
            + ", pageWidth=" + pageWidth + ", pageHeight=" + pageHeight
            + ", content=" + content + "]";
}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM