import com.itextpdf.awt.geom.Rectangle2D.Float;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SealXYUtil {
public static void xyxxxx() throws IOException {
//1.给定文件
File pdfFile = new File("C:\Users\Admin\Desktop\1.pdf");
//2.定义一个byte数组,长度为文件的长度
byte[] pdfData = new byte[(int) pdfFile.length()];
//3.IO流读取文件内容到byte数组
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(pdfFile);
inputStream.read(pdfData);
} catch (IOException e) {
throw e;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
}
}
}
//4.指定关键字
String keyword = "我爱我的祖国";
//5.调用方法,给定关键字和文件
List<float[]> positions = findKeywordPostions(pdfData, keyword);
//6.返回值类型是 List<float[]> 每个list元素代表一个匹配的位置,分别为 float[0]所在页码 float[1]所在x轴 float[2]所在y轴
System.out.println("total:" + positions.size());
if (positions != null && positions.size() > 0) {
for (float[] position : positions) {
System.out.print("pageNum: " + (int) position[0]);
System.out.print("\tx: " + position[1]);
System.out.println("\ty: " + position[2]);
}
}
}
/**
* findKeywordPostions
*
* @param pdfData 通过IO流 PDF文件转化的byte数组
* @param keyword 关键字
* @return List<float [ ]> : float[0]:pageNum float[1]:x float[2]:y
* @throws IOException
*/
public static List<float[]> findKeywordPostions(byte[] pdfData, String keyword) throws IOException {
List<float[]> result = new ArrayList<>();
List<PdfPageContentPositions> pdfPageContentPositions = getPdfContentPostionsList(pdfData);
for (PdfPageContentPositions pdfPageContentPosition : pdfPageContentPositions) {
List<float[]> charPositions = findPositions(keyword, pdfPageContentPosition);
if (charPositions == null || charPositions.size() < 1) {
continue;
}
result.addAll(charPositions);
}
return result;
}
private static List<PdfPageContentPositions> getPdfContentPostionsList(byte[] pdfData) throws IOException {
PdfReader reader = new PdfReader(pdfData);
List<PdfPageContentPositions> result = new ArrayList<>();
int pages = reader.getNumberOfPages();
for (int pageNum = 1; pageNum <= pages; pageNum++) {
float width = reader.getPageSize(pageNum).getWidth();
float height = reader.getPageSize(pageNum).getHeight();
PdfRenderListener pdfRenderListener = new PdfRenderListener(pageNum, width, height);
//解析pdf,定位位置
PdfContentStreamProcessor processor = new PdfContentStreamProcessor(pdfRenderListener);
PdfDictionary pageDic = reader.getPageN(pageNum);
PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
try {
processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);
} catch (IOException e) {
reader.close();
throw e;
}
String content = pdfRenderListener.getContent();
List<CharPosition> charPositions = pdfRenderListener.getcharPositions();
List<float[]> positionsList = new ArrayList<>();
for (CharPosition charPosition : charPositions) {
float[] positions = new float[]{
charPosition.getPageNum(), charPosition.getX(), charPosition.getY()};
positionsList.add(positions);
}
PdfPageContentPositions pdfPageContentPositions = new PdfPageContentPositions();
pdfPageContentPositions.setContent(content);
pdfPageContentPositions.setPostions(positionsList);
result.add(pdfPageContentPositions);
}
reader.close();
return result;
}
private static List<float[]> findPositions(String keyword, PdfPageContentPositions pdfPageContentPositions) {
List<float[]> result = new ArrayList<>();
String content = pdfPageContentPositions.getContent();
List<float[]> charPositions = pdfPageContentPositions.getPositions();
for (int pos = 0; pos < content.length(); ) {
int positionIndex = content.indexOf(keyword, pos);
if (positionIndex == -1) {
break;
}
float[] postions = charPositions.get(positionIndex);
result.add(postions);
pos = positionIndex + 1;
}
return result;
}
private static class PdfPageContentPositions {
private String content;
private List<float[]> positions;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public List<float[]> getPositions() {
return positions;
}
public void setPostions(List<float[]> positions) {
this.positions = positions;
}
}
private static class PdfRenderListener implements RenderListener {
private int pageNum;
private float pageWidth;
private float pageHeight;
private StringBuilder contentBuilder = new StringBuilder();
private List<CharPosition> charPositions = new ArrayList<>();
public PdfRenderListener(int pageNum, float pageWidth, float pageHeight) {
this.pageNum = pageNum;
this.pageWidth = pageWidth;
this.pageHeight = pageHeight;
}
public void beginTextBlock() {
}
public void renderText(TextRenderInfo renderInfo) {
List<TextRenderInfo> characterRenderInfos = renderInfo.getCharacterRenderInfos();
for (TextRenderInfo textRenderInfo : characterRenderInfos) {
String word = textRenderInfo.getText();
if (word.length() > 1) {
word = word.substring(word.length() - 1, word.length());
}
Float rectangle = textRenderInfo.getAscentLine().getBoundingRectange();
float x = (float) rectangle.getX();
float y = (float) rectangle.getY();
// float x = (float)rectangle.getCenterX();
// float y = (float)rectangle.getCenterY();
// double x = rectangle.getMinX();
// double y = rectangle.getMaxY();
//这两个是关键字在所在页面的XY轴的百分比
float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;
// CharPosition charPosition = new CharPosition(pageNum, xPercent, yPercent);
CharPosition charPosition = new CharPosition(pageNum, (float) x, (float) y);
charPositions.add(charPosition);
contentBuilder.append(word);
}
}
public void endTextBlock() {
}
public void renderImage(ImageRenderInfo renderInfo) {
}
public String getContent() {
return contentBuilder.toString();
}
public List<CharPosition> getcharPositions() {
return charPositions;
}
}
private static class CharPosition {
private int pageNum = 0;
private float x = 0;
private float y = 0;
public CharPosition(int pageNum, float x, float y) {
this.pageNum = pageNum;
this.x = x;
this.y = y;
}
public int getPageNum() {
return pageNum;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
@Override
public String toString() {
return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";
}
}
}
maven地址
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
通过指定关键字,获取关键字所处的页码和xy坐标。
经测试,真实有效!
文章浏览阅读165次。加入水印,采用lsb%Name: Chris Shoemaker%Course: EER-280 - Digital Watermarking%Project: Least Significant Bit Substitution% Watermark Embedingclear all;% save start timestart_time=cputime;% read in the co..._[cover_object,map]=imread(file_name);
文章浏览阅读1.6w次。原文地址:http://www.xitongtiandi.net/wenzhang/win10/12654.htmlWin10专业版下ipv6无网络访问权限解决方案(只在win10专业版下做了测试,win7和win8.1待测试)1、首先打开 https://support.microsoft.com/en-us/kb/929852 选择Re-enable IPv6 相关的_ipv6无internet访问权限怎么办
文章浏览阅读3.1k次,点赞32次,收藏37次。而且每次都要直接使用上一步骤的具体运算结果(如2,6,24等),也不方便,应当能找到一种通用的表示方法。由于数值运算往往有现成的模型,可以运用数值分析方法,因此对数值运算的算法的研究比较深入,算法比较成熟。从图中可以看出:“其他”这一部分,包括不能被4整除的年份,以及能被4整除,又能被100整除,但不能被400整除的那些年份(如1900年),它们都是非闰年。:若year能被4整除,不能被100整除,则输出year的值和“是闰年”。因此,上述算法不仅是正确的,而且是计算机能方便实现的较好的算法。_程序等于数据结构+算法
文章浏览阅读2.6w次,点赞18次,收藏88次。记录一下碰到的问题解决方法第一步:首先最先要确定的是芯片和设置是否对应!!!!!!!!!第二步:确定芯片和设置对应无误后,再考虑下面的方法Keil : Error-Flash Download failed Cortex-M4错误解决方案整理在开发 nRF51822/nRF52832/nRF52840时候出现如下如下问题:问题: Keil电子下载时候出现 Error: Flash Download failed - "Cortex-M4"的错误,如下图根据官方教程解释如下,还是发现不容易解决,另_error: flash download failed - "cortex-m4
文章浏览阅读313次。在数据库编程中,很多朋友会碰到分割字符串的需求,一般都是分割成一列多行模式,但也有时会需要分割成多列一行的模式,下面我们来看下如何实现这种需求。首先创建一个辅助函数,来得到生成多列的SQL语句:create function toArray(@str nvarchar(1000),@sym nvarchar(10))returns nvarchar(3000)asbe..._sqlserver 字符串分割成多列 小提琴
文章浏览阅读1.3k次。配置MM32微控制器引脚复用功能文章目录配置MM32微控制器引脚复用功能IntroductionAlgorithmGPIOx_CR寄存器GPIOx_AFR寄存器GPIOx_CR & GPIOx_AFR寄存器TIMUARTSPI_MASTERSPI_SLAVEI2CCANADCFSMCQSPIDACCOMPSDIOUSBPraticeConclusionIntroduction使用过NXP(FSL)微控制器的开发者在配置引脚复用功能时,直接在PORT模块中,对应引脚的的PCR寄存器的MUX字段_mm32f单片机的bootloader串行口引脚
文章浏览阅读88次。 &n..._简明易懂 机器学习
文章浏览阅读134次。[color=darkred][size=x-large]存储过程学习总结[/size][/color][size=medium]1、存储过程基本语法:[/size]create procedure sp_name()begin ......end;[size=medium]2、如何调用:[/size]call sp_name();[size=medium]..._存储过程repeatuse near 'end repeat; close curgra;
文章浏览阅读97次。Neil Fraser文章看得糊里糊涂,e文不是很好...一般我们加载数据会生成一个script标签,在onload事件里remove掉,或者在jsonp回调函数中remove掉script标签,取得数据这样其实script占用的内存并没有释放,必须:for (var prop in jsFile) { delete jsFile[prop];}ie下不能d..._script加载的数据在哪里
文章浏览阅读77次。JavaScript 程序应该尽量放在 .js 的文件中,需要调用的时候在 HTML 中以 <script src="filename.js"> 的形式包含进来。JavaScript 代码若不是该 HTML 文件所专用的,则应尽量避免在 HTML 文件中直接编写 JavaScript 代码。因为这样会大大增加 HTML 文件的大小,无益于代码的压缩和缓存的使用。<scr..._js里的下载路径怎么做约束
文章浏览阅读604次。作者:池建强网址:macshuo.com微信:sagacity-mac问:池老师,我是个不爱互动的人,但是您所有的文章我都看了,非常感谢您的引导,我入手了人生第一台 MBP。现在问题来了,但是找不到更合适的人解答,只能求助于您了,如果您有时间的话。问题是这样的:我有个32bit unix file(开启一个服务进程),在 Mac 上执行时错误提示是:exec f_程序员价值
文章浏览阅读143次。测试工作总体流程图_测试的工作流程