导读:近期要做一个根据关键字定位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 + "]"; } }