`
珊瑚成长日记
  • 浏览: 21029 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

PDF数据解析

    博客分类:
  • java
 
阅读更多

 系统中有一个读取PDF表单的数据,然后将数据按字段解析出来,存储到数据库的功能。实现思路,大致是先获取PDF的流,把数据导入到xml中,然后逐行读取xml的数据。具体的实现代码有点挫...

package com.rb.common.pdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;

import com.itextpdf.text.DocumentException;
import com.rb.owk.commons.lang.base.orm.BusinessException;

/**
 * 解析PDF报表T-Q-1,提取报表数据
 * 
 * @author HO274509
 * 
 */
public class PdfTQ1 {
	private PdfTQ1() {
	}

	private final static Log log = LogFactory.getLog(PdfTQ1.class);
	// 要解析的PDF
	public static final String RESOURCE = "/pdf/T-Q-1.pdf";// classpath相对路径
	// 要填充PDF的XML数据来源
	public static final String XMLDATA = "T-Q-1.xml";
	// 填充之前的PDF
	public static final String SOURCE = "T-Q-1.pdf";
	// 填充之后的PDF
	public static final String RESULT = "T-Q-1_fill.pdf";

	/**
	 * 打印pdf数据
	 * 
	 * @throws TransformerException
	 * @throws TransformerFactoryConfigurationError
	 * @throws SAXException
	 * @throws ParserConfigurationException
	 * @throws IOException
	 */
	public static void printPdfData() throws IOException,
			ParserConfigurationException, SAXException,
			TransformerFactoryConfigurationError, TransformerException {
		/**
		 * 获取xml格式数据
		 */
		InputStream in = PdfTQ4.class.getResourceAsStream(RESOURCE);
//		 另一种获取方法  PdfUtil.getXFAData(RESOURCE, file);
		ByteArrayOutputStream os = PdfUtil.getXFAData(in);
		ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
		/**
		 * 使用dom4j解析xml,获取数据
		 */

		SAXReader xmlReader = new SAXReader();
		org.dom4j.Document document = null;
		try {
			// document = xmlReader.read(xml);
			document = xmlReader.read(is);
		} catch (org.dom4j.DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			log.error("log4j解析出错");
		}
		// 根节点
		Element root = document.getRootElement();
		// 表单根节点
		Element element = root.element("T_Q_1");
		// 填报人相关信息
		log.info("-----填报人信息-----");
		log.info(String.format("填报部门:%s", element.element("FILLIN_DEPT")
				.getText()));
		log.info(String.format("填报人:%s", element.element("FILLIN_PERSON")
				.getText()));
		log.info(String.format("联系电话:%s", element.element("TELEPHONE")
				.getText()));
		log.info(String.format("责任人:%s", element.element("RES_PERSON")
				.getText()));

		log.info("-----重要信息系统的停止服务情况-----");
		// 表单TQ1001数据根节点:停止服务性质为非预期停止服务的系统停止服务情况
		Iterator<Element> it_TQ1001 = element.elementIterator("TQ1001");
		int index = 1;
		while (it_TQ1001.hasNext()) {// 打印非预期停止服务的系统停止服务情况
			Element TQ1001 = it_TQ1001.next();
			log.info("停止服务性质:非预期停止服务");
			log.info(String.format("序号:%s", index));
			log
					.info(String.format("信息系统:%s", TQ1001.element("COL1")
							.getText()));
			if (StringUtils.isNotEmpty(TQ1001.elementText("COL2"))) {
				log.info(String.format("备注:%s", TQ1001.elementText("COL2")));
			}
			log.info(String.format("停止服务原因:%s", TQ1001.elementText("COL3")));
			if (StringUtils.isNotEmpty(TQ1001.elementText("COL4"))) {
				log.info(String.format("备注:%s", TQ1001.elementText("COL4")));
			}
			log.info(String.format("事件等级:%s", TQ1001.elementText("COL5")));
			log.info(String.format("起始时间:%s", TQ1001.elementText("COL6")));
			log.info(String.format("结束时间:%s", TQ1001.elementText("COL7")));
			log.info(String.format("影响范围:%s", TQ1001.elementText("COL8")));
			if (StringUtils.isNotEmpty(TQ1001.elementText("COL9"))) {
				log.info(String.format("个数:%s", TQ1001.elementText("COL9")));
			}
			log.info(String.format("描述:%s", TQ1001.elementText("COL10")));
			index++;
		}
		// 表单TQ1003数据根节点:停止服务性质为预期停止服务的系统停止服务情况
		Iterator<Element> it_TQ1003 = element.elementIterator("TQ1003");
		index = 1;
		while (it_TQ1003.hasNext()) {// 打印停止服务的系统停止服务情况
			Element TQ1002 = it_TQ1003.next();
			log.info("停止服务性质:预期停止服务");
			log.info(String.format("序号:%s", index));
			log
					.info(String.format("信息系统:%s", TQ1002.element("COL1")
							.getText()));
			if (StringUtils.isNotEmpty(TQ1002.elementText("COL7"))) {
				log.info(String.format("备注:%s", TQ1002.elementText("COL7")));
			}
			log.info(String.format("停止服务原因:%s", TQ1002.elementText("COL2")));
			if (StringUtils.isNotEmpty(TQ1002.elementText("COL8"))) {
				log.info(String.format("备注:%s", TQ1002.elementText("COL8")));
			}
			log.info(String.format("起始时间:%s", TQ1002.elementText("COL3")));
			log.info(String.format("结束时间:%s", TQ1002.elementText("COL4")));
			log.info(String.format("影响范围:%s", TQ1002.elementText("COL10")));
			if (StringUtils.isNotEmpty(TQ1002.elementText("COL9"))) {
				log.info(String.format("个数:%s", TQ1002.elementText("COL9")));
			}
			log.info(String.format("描述:%s", TQ1002.elementText("COL6")));
			index++;
		}
		// 表单TQ1006数据根节点:核心业务系统重要性能指标
		Element TQ1006 = element.element("TQ1006");
		log.info("-----核心系统重要性能指标-----");
		log.info(String.format("系统可用率-->数量:%s,备注:%s", TQ1006.element("COL1")
				.getText(), TQ1006.element("COL19").getText()));
		log.info(String.format("批处理的平均批处理用时-->数量:%s,备注:%s", TQ1006.element(
				"COL2").getText(), TQ1006.element("COL20").getText()));
		log.info(String.format("CPU平均使用率-->数量:%s,备注:%s", TQ1006.element("COL3")
				.getText(), TQ1006.element("COL21").getText()));
		log.info(String.format("CPU高峰使用率-->数量:%s,备注:%s", TQ1006.element("COL4")
				.getText(), TQ1006.element("COL22").getText()));
		log.info(String.format("内存平均使用率-->数量:%s,备注:%s", TQ1006.element("COL5")
				.getText(), TQ1006.element("COL23").getText()));
		log.info(String.format("磁盘空间占有率峰值-->数量:%s,备注:%s", TQ1006
				.element("COL8").getText(), TQ1006.element("COL26").getText()));
		log.info(String.format("处理能力---"));
		log.info(String.format("日均交易笔数-->数量:%s,备注:%s", TQ1006.element("COL9")
				.getText(), TQ1006.element("COL27").getText()));
		log.info(String.format("日交易笔数峰值-->数量:%s,备注:%s", TQ1006.element("COL10")
				.getText(), TQ1006.element("COL28").getText()));
		log.info(String.format("系统可承载的最大交易并发数-->数量:%s,备注:%s", TQ1006.element(
				"COL11").getText(), TQ1006.element("COL29").getText()));
		log.info(String.format("交易成功率-->数量:%s,备注:%s", TQ1006.element("COL12")
				.getText(), TQ1006.element("COL30").getText()));
		log.info(String.format("账户数及变动---"));
		log.info(String.format("公司账户及增减---"));
		log
				.info(String.format("公司账户:%s,同比:%s,环比:%s,备注:%s", TQ1006
						.element("COL13").getText(), TQ1006.element("COL14")
						.getText(), TQ1006.element("COL15").getText(), TQ1006
						.element("COL31").getText()));
		log.info(String.format("个人账户及增减---"));
		log
				.info(String.format("个人账户:%s,同比:%s,环比:%s,备注:%s", TQ1006
						.element("COL16").getText(), TQ1006.element("COL17")
						.getText(), TQ1006.element("COL18").getText(), TQ1006
						.element("COL32").getText()));
		// 表单TQ1007数据根节点:
		Element TQ1007 = element.element("TQ1007");
		log.info("-----核心网络系统运行情况-----");
		log.info(String.format("业务时段平均带宽占用情况(生产中心或中心机房到一级分支机构):%s,备注:%s",
				TQ1007.elementText("COL1"), TQ1007.elementText("COL15")));
		log.info(String.format("业务时段平均带宽占用情况(互联网出口):%s,备注:%s", TQ1007
				.elementText("COL2"), TQ1007.elementText("COL16")));
		log.info("------网上银行系统运行情况-----");
		log.info(String.format("日均交易笔数 数量:%s,备注:%s",
				TQ1007.elementText("COL3"), TQ1007.elementText("COL17")));
		log.info(String.format("日交易笔数峰 数量:%s,备注:%s",
				TQ1007.elementText("COL4"), TQ1007.elementText("COL18")));
		log.info(String.format("系统可承载的最大交易并发 数量:%s,备注:%s", TQ1007
				.elementText("COL5"), TQ1007.elementText("COL19")));
		log.info(String.format("平均在线并发用户数 数量:%s,备注:%s", TQ1007
				.elementText("COL6"), TQ1007.elementText("COL20")));
		log.info(String.format("最大在线并发用户数 数量:%s,备注:%s", TQ1007
				.elementText("COL7"), TQ1007.elementText("COL21")));
		log.info(String.format("系统可承载的最大在线并发数 数量:%s,备注:%s", TQ1007
				.elementText("COL8"), TQ1007.elementText("COL22")));
		log.info("-----银行卡系统运行情况-----");
		log.info(String.format("日均交易笔数 数量:%s,备注:%s",
				TQ1007.elementText("COL9"), TQ1007.elementText("COL23")));
		log.info(String.format("日交易笔数峰数 数量:%s,备注:%s", TQ1007
				.elementText("COL10"), TQ1007.elementText("COL24")));
		log.info(String.format("系统可承载的最大交易并发数 数量:%s,备注:%s", TQ1007
				.elementText("COL11"), TQ1007.elementText("COL25")));
		log.info("-----第三方存管系统运行情况-----");
		log.info(String.format("日均交易笔数 数量:%s,备注:%s", TQ1007
				.elementText("COL12"), TQ1007.elementText("COL26")));
		log.info(String.format("日交易笔数峰数 数量:%s,备注:%s", TQ1007
				.elementText("COL13"), TQ1007.elementText("COL27")));
		log.info(String.format("系统可承载的最大交易并发数 数量:%s,备注:%s", TQ1007
				.elementText("COL14"), TQ1007.elementText("COL28")));
		log.info("-----数据中心(中心机房)外部异常情况-----");
		log.info(String.format("数据中心市电中断次数 数量:%s,备注:%s", TQ1007
				.elementText("COL29"), TQ1007.elementText("COL30")));
		log.info(String.format("数据中心由于外部原因导致网络通讯中断次数 数量:%s,备注:%s", TQ1007
				.elementText("COL31"), TQ1007.elementText("COL32")));
	}

	public static Map<String, Object> getTq1Data() throws IOException,
			ParserConfigurationException, SAXException,
			TransformerFactoryConfigurationError, TransformerException {
		Map<String, Object> tq1Map = new HashMap<String, Object>();
		/**
		 * 获取xml格式数据
		 */
		InputStream in = PdfTQ4.class.getResourceAsStream(RESOURCE);
		ByteArrayOutputStream os = PdfUtil.getXFAData(in);
		ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
		/**
		 * 使用dom4j解析xml,获取数据
		 */

		SAXReader xmlReader = new SAXReader();
		org.dom4j.Document document = null;
		try {
			// document = xmlReader.read(xml);
			document = xmlReader.read(is);
		} catch (org.dom4j.DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			log.error("log4j解析出错");
		}
		// PDF报表在adobe life cycle表单设计里的结构是:pdf报表标识符-》多个表单-》表单内嵌套有数据节点或者子表单
		// PDF报表的XML数据结构(基本一致,就这四层):ROOT-》报表标识节点-》各个表单根节点=》表单内部数据节点
		// 根节点
		Element root = document.getRootElement();
		// 报表根节点
		Element element = root.element("T_Q_1");
		// 填报人相关信息
		tq1Map.put("ISEMPTY", element.elementText("isempty"));
		tq1Map.put("FILLINDEPT", element.elementText("FILLIN_DEPT"));
		tq1Map.put("FILLINPERSON", element.elementText("FILLIN_PERSON"));
		tq1Map.put("TELEPHONE", element.elementText("TELEPHONE"));
		tq1Map.put("RESPERSON", element.elementText("RES_PERSON"));
		List<Map<String, Object>> tq1001List = new ArrayList<Map<String,Object>>();
		Iterator<Element> it_TQ1001 = element.elementIterator("TQ1001");
		int i=1;
		while (it_TQ1001.hasNext()) {
			Element tq1001 = it_TQ1001.next();
			Iterator<Element> it = tq1001.elementIterator();
			Map<String , Object> tq1001Map = new HashMap<String, Object>();
			tq1001Map.put("INDEX", i++);
			while (it.hasNext()) {
				Element tmp = it.next();
				log.info(tmp.getName() + ":::::::" + tmp.getTextTrim());
				tq1001Map.put(tmp.getName(), tmp.getTextTrim());
			}
			if(StringUtils.isEmpty((String)tq1001Map.get("COL9"))){
				tq1001Map.put("COL9", null);
			}
			tq1001List.add(tq1001Map);
		}
		tq1Map.put("tq1001List", tq1001List);
		List<Map<String, Object>> tq1003List = new ArrayList<Map<String,Object>>();
		Iterator<Element> it_TQ1003 = element.elementIterator("TQ1003");
		i=1;
		while (it_TQ1003.hasNext()) {
			Element tq1003 = it_TQ1003.next();
			Iterator<Element> it = tq1003.elementIterator();
			Map<String , Object> tq1003Map = new HashMap<String, Object>();
			tq1003Map.put("INDEX", i++);
			while (it.hasNext()) {
				Element tmp = it.next();
				log.info(tmp.getName() + ":::::::" + tmp.getTextTrim());
				tq1003Map.put(tmp.getName(), tmp.getTextTrim());
			}
			if(StringUtils.isEmpty((String)tq1003Map.get("COL9"))){
				tq1003Map.put("COL9", null);
			}
			tq1003List.add(tq1003Map);
		}
		tq1Map.put("tq1003List", tq1003List);
		Element TQ1006 = element.element("TQ1006");
		Iterator<Element> it_TQ1006 = TQ1006.elementIterator();
		while (it_TQ1006.hasNext()) {
			Element tmp = it_TQ1006.next();
			log.info(tmp.getName() + ":::::::" + tmp.getTextTrim());
			tq1Map.put(tmp.getName(), tmp.getTextTrim());
		}
		Element TQ1007 = element.element("TQ1007");
		Iterator<Element> it_TQ1007 = TQ1007.elementIterator();
		while (it_TQ1007.hasNext()) {
			Element tmp = it_TQ1007.next();
			log.info(tmp.getName()+"TQ1007" + ":::::::" + tmp.getTextTrim());
			tq1Map.put(tmp.getName()+"TQ1007", tmp.getTextTrim());
		}

		return tq1Map;
	}

	/**
	 * 填充成新的pdf之后,会提示pdf文档自创建后被修改,无法再使用扩展功能,这个不知道为什么
	 * 
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static void fillPdf() throws IOException, DocumentException {
		PdfUtil.manipulatePdf(RESOURCE, XMLDATA, RESULT);
	}

	public static void main(String[] args) throws IOException,
			ParserConfigurationException, SAXException,
			TransformerFactoryConfigurationError, TransformerException,
			DocumentException, BusinessException {
		// 提取pdf数据,打印
		printPdfData();
		// // 以XML形式导出pdf数据
		File file = new File(XMLDATA);
		PdfUtil.getXFAData(RESOURCE, file);
		// 根据模板和数据生成PDF
		fillPdf();

	}
}

 调用的pdfutil代码如下

 

package com.rb.common.pdf;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.XfaForm;

/**
 * pdf工具类 
 * 依赖ITEXT
 * @author HO274509
 *
 */
public class PdfUtil {

	/**
	 * Reads the data from a PDF containing an XFA form.
	 * 解析基于XML Forms Architecture的pdf,导出xml形式的表单数据写入到文件中
	 * @param src
	 *            the original PDF
	 * @param dest
	 *            the data in XML format
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws TransformerFactoryConfigurationError
	 * @throws TransformerException
	 */
	public static void getXFAData(String src, File file) throws IOException,
			ParserConfigurationException, SAXException,
			TransformerFactoryConfigurationError, TransformerException {
		FileOutputStream os = new FileOutputStream(file);
		PdfReader reader = new PdfReader(src);
		XfaForm xfa = new XfaForm(reader);
		Node node = xfa.getDatasetsNode();
		NodeList list = node.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			if ("data".equals(list.item(i).getLocalName())) {
				node = list.item(i);
				break;
			}
		}
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		tf.setOutputProperty(OutputKeys.INDENT, "yes");
		tf.transform(new DOMSource(node), new StreamResult(os));
		reader.close();
	}
	
	/**
	 * Reads the data from a PDF containing an XFA form.
	 * 解析基于XML Forms Architecture的pdf,导出xml形式的表单数据写入到文件中
	 * @param src
	 *            the original PDF
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws TransformerFactoryConfigurationError
	 * @throws TransformerException
	 */
	public static ByteArrayOutputStream getXFAData(InputStream is) throws IOException,
			ParserConfigurationException, SAXException,
			TransformerFactoryConfigurationError, TransformerException {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		PdfReader reader = new PdfReader(is);
		XfaForm xfa = new XfaForm(reader);
		Node node = xfa.getDatasetsNode();
		NodeList list = node.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			if ("data".equals(list.item(i).getLocalName())) {
				node = list.item(i);
				break;
			}
		}
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		tf.setOutputProperty(OutputKeys.INDENT, "yes");
		tf.transform(new DOMSource(node), new StreamResult(os));
		reader.close();
		return os;
	}
	/**
	 * Reads the data from a PDF containing an XFA form.
	 * 解析基于XML Forms Architecture的pdf,导出xml形式的表单数据写入到文件中
	 * @param src
	 *            the original PDF
	 * @param dest
	 *            the data in XML format
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws TransformerFactoryConfigurationError
	 * @throws TransformerException
	 */
	public static void getXFAData(InputStream is, File file) throws IOException,
			ParserConfigurationException, SAXException,
			TransformerFactoryConfigurationError, TransformerException {
		FileOutputStream os = new FileOutputStream(file);
		PdfReader reader = new PdfReader(is);
		XfaForm xfa = new XfaForm(reader);
		Node node = xfa.getDatasetsNode();
		NodeList list = node.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			if ("data".equals(list.item(i).getLocalName())) {
				node = list.item(i);
				break;
			}
		}
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		tf.setOutputProperty(OutputKeys.INDENT, "yes");
		tf.transform(new DOMSource(node), new StreamResult(os));
		reader.close();
	}
	
	/**
	 * Checks if a PDF containing an interactive form uses AcroForm technology,
	 * XFA technology, or both. Also lists the field names.
	 * 
	 * 不支持adobe designer设计的xfa格式的pdf
	 * @param src
	 *            the original PDF
	 * @param dest
	 *            a text file containing form info.
	 * @throws IOException
	 */
	public void getFieldnames(String src, String dest) throws IOException {
		PrintStream out = new PrintStream(new FileOutputStream(dest));
		PdfReader reader = new PdfReader(src);
		AcroFields form = reader.getAcroFields();
		XfaForm xfa = form.getXfa();
		out.println(xfa.isXfaPresent() ? "XFA form" : "AcroForm");
		Set<String> fields = form.getFields().keySet();
		for (String key : fields) {
			out.println(key);
		}
		out.flush();
		out.close();
	}
	/**
	 * Reads the XML that makes up an XFA form.
	 * 
	 * @param src
	 *            the original PDF file
	 * @param dest
	 *            the resulting XML file
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws TransformerFactoryConfigurationError
	 * @throws TransformerException
	 */
	public void readXfa(String src, String dest) throws IOException,
			ParserConfigurationException, SAXException,
			TransformerFactoryConfigurationError, TransformerException {
		FileOutputStream os = new FileOutputStream(dest);
		PdfReader reader = new PdfReader(src);
		XfaForm xfa = new XfaForm(reader);
		Document doc = xfa.getDomDocument();
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		tf.setOutputProperty(OutputKeys.INDENT, "yes");
		tf.transform(new DOMSource(doc), new StreamResult(os));
		reader.close();
	}
	
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param xml the XML data that needs to be added to the XFA form
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public static void manipulatePdf(String src, String xml, String dest)
        throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader,
                new FileOutputStream(dest), '\0', true);
        AcroFields form = stamper.getAcroFields();
        XfaForm xfa = form.getXfa();
        xfa.fillXfaForm(new FileInputStream(xml));
        stamper.close();
    }
	
}

 

分享到:
评论

相关推荐

    PDF结构解析(c++源代码)

    总之,PDF的解析是一项涉及多个层次的技术任务,需要对PDF规范有深入的理解,并能用C++有效地处理二进制数据。通过编写和调试PDF解析器,不仅可以掌握PDF的结构,还能提升C++编程技巧和文件处理能力。

    PDF结构解析

    在C++中解析PDF,你需要创建一个解析器来读取PDF的二进制流,并将其转化为可操作的数据结构。这通常涉及到以下步骤: 1. **文件头识别**:PDF文件通常以"%PDF-"开头,这是PDF版本的标识。解析器首先需要识别这个...

    AIS数据解析.pdf

    B类AIS船载设备通常安装在这些船舶上,它可以根据船舶动态信息的解码过程,通过串口服务器接收并解析AIS报文,为船舶提供实时的位置信息和船舶动态数据,从而提高航行安全。 总结来说,AIS报文解析涉及多个方面,...

    nmea.rar_GPS信号解析_GPS数据处理_NMEA解析_数据解析_解析nmea

    标题中的“nmea.rar”指的是一个压缩文件,包含了与NMEA(北美海洋电子...它可能包含理论介绍、代码示例、最佳实践等内容,帮助用户掌握GPS数据解析和处理的技巧,从而开发出能够准确获取和利用GPS信息的应用或系统。

    AIS数据解析,ais数据解析 c语言

    AIS(Automatic Identification System)是一种船舶自动识别系统,主要用于海上航行安全,通过VHF(甚高频)无线电通信网络,...《AIS数据解析.pdf》这份文档很可能会提供详细的步骤和示例,帮助你深入了解这个过程。

    电子发票解析软件 1.解析pdf电子发票数据,选择发票目录批量自动解析,生成解析统计excel文件 2.可以自动从邮箱下载发票文

    1.解析pdf,ofd,扫描图片电子发票数据,选择发票目录批量自动解析,生成解析统计excel文件 2.编辑解析的电子发票内容数据 3.导出打包电子发票数据,发票文件名可以选择多种命名方式 4.pdf相关工具:pdf转图片,ofd转...

    美国HIPAA隐私规则对于个人健康医疗数据合规解析.pdf

    美国HIPAA隐私规则对于个人健康医疗数据合规解析.pdf美国HIPAA隐私规则对于个人健康医疗数据合规解析.pdf美国HIPAA隐私规则对于个人健康医疗数据合规解析.pdf美国HIPAA隐私规则对于个人健康医疗数据合规解析.pdf美国...

    JAVA 解析电子发票 解析PDF 精准读取想要的数据 源码+JAR包

    最近有个项目是要求将PDF版的电子发票,解析成文本格式,要求各个名称都对应,刚开始用的是PDFTextStripper.getText(),发现不能准确的抓到自己想要的数据,后来想了个办法,使用Rectangle,画多个矩形,精准定位,...

    java代码pdf解析成xml.rar

    Java代码PDF解析成XML是一项技术任务,涉及到Java编程语言、PDF文档处理和XML数据格式转换。在这个场景中,我们主要关注如何使用Java库iTextPDF将PDF文档中的内容解析为XML结构。 首先,我们需要理解PDF(Portable ...

    电子发票识别,电子发票解析,可识别 电子普票 电子专票 pdf ofd格式解析,数电票pdf解析

    而OFD(Open Financial Document)是我国国家标准规定的电子发票格式,其结构化程度更高,更适合于数据解析。 解析电子发票的核心在于理解其结构和数据标准。PDF和OFD文件内部都包含结构化的数据元素,这些元素按照...

    Java 解析 PDF, pdfbox读取PDF内容

    本文将深入探讨如何使用PDFBox库在Java中解析PDF并读取其内容。 PDFBox是Apache软件基金会的一个开源项目,它为Java开发者提供了一系列API来操作PDF文档,包括读取、创建、编辑以及签署PDF等任务。在本示例中,我们...

    java解析pdf

    在Java中解析PDF文件是一项常见的任务,特别是在处理用户提交的文档、数据分析或自动化报告等场景下。本篇文章将深入探讨如何使用Java来解析PDF文件,并提供一个实际的示例。 Java解析PDF主要依赖于第三方库,如...

    pdf文件解析,用文件流方式处理

    PDF文件解析是理解PDF文件结构、提取数据或进行编辑操作的关键步骤。在这里,我们将深入探讨如何使用文件流方式来处理PDF文件。 首先,我们需要了解PDF的基本结构。PDF文件由一系列的对象组成,包括页面、字体、...

    PDF解析jar包

    PDF解析jar包是一种Java开发工具,它包含了处理和解析PDF文档所需的各种类库和方法。在Java编程中,处理PDF文件通常需要借助第三方库,这样的jar包就是其中一种解决方案。PDF(Portable Document Format)是一种通用...

    web版pdf自解析查看器

    1. 加载和解析PDF文档:PDF.js能够读取PDF文件的元数据,并解析出每个页面的内容。 2. 渲染页面:使用HTML5 Canvas将PDF页面分解为文字、图像、线条等元素,然后在浏览器中逐像素渲染。 3. 缩放和滚动:用户可以平移...

    PDF矢量数据解析引擎介绍.docx

    PDF矢量数据解析引擎是一种专门用于处理包含矢量数据的PDF文档的技术,它能够解析PDF文件中的几何形状、线条和曲线,并对其进行操作,如投影转换、裁剪等,以适应不同的应用场景,尤其在地理信息系统(GIS)中显示...

    C++解析PDF文件

    6. **图像和资源管理**:PDF文件中可能包含JPEG、PNG等图像,解析时需要识别并解码这些图像数据。同时,PDF还可能包含其他资源,如颜色空间、渐变和模板。 7. **解析表单和交互元素**:对于包含表单的PDF,解析器还...

    用Java读取pdf中的数据

    本篇文章将详细介绍如何使用Java进行PDF数据的读取,并围绕`PdfReader`这个概念展开。 首先,`PdfReader`通常指的是一个类,存在于某些PDF处理库中,如iText或PDFBox,它的主要功能是打开并解析PDF文件,为后续的...

    PDF解析SDK

    12.可直接解析指定页的PDF数据,与页面顺序无关。 13.支持日文的处理。 14.支持超级链接的提取。 15.支持直接将PDF文档变为HTM文档。 联系方式: 主页:http://www.pdfimage.com E-mail: pdfimage@pdfimage...

Global site tag (gtag.js) - Google Analytics