精华内容
下载资源
问答
  • java解析docx获取文字图片并识别图片准确位置需求简述功能模块版本1生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的...

    java解析docx获取文字图片并识别图片准确位置

    需求简述

    首先简单介绍一下我开发时的需求,做的是一个考试系统,负责的功能模块是试题导入,导入分为excel导入和word导入,个人认为excel导入很方便,word相对来说麻烦一点,用户体验相对较差,但是怎么办呢,领导要求的啊,别人有的我们也要有,没错,就是这么强势!!!言归正传,需求就是,给用户提供一个word模板,用户在模板里面按照特定的格式将题目信息填写到docx中,上传到系统中,系统将word中的一堆文字解析成对应的实体,存入数据库,其中的难点包括:
    1.如何将整个文档的所有文字图片信息分隔成一个个单个的实体数据;
    2.如何知道文档中的图片属于哪段文字也就是属于分隔之后的哪个实体信息;
    3.就算知道是哪个实体信息中的图片之后,如果有多张图片,如何知道其具体位置;

    功能模块版本1

    最开始的需求并不是要求一道题目可以添加多张图片,也就是开始的需求是一道题目只允许用户上传一张图片,作为题干的图片拼接在题干的最后面;后来又改成了不仅题干允许用户自由发挥插入多张图片,选项也是同样需要支持多张图片,这里是最坑的,导致后面代码改动比较大;先说说前者的实现思路吧;
    1.首先考虑到docx的格式是主流,所以系统中只支持docx文件格式的word上传,在实现这块功能的时候最开始使用的是poi技术,后面发现poi在excel方面解析还可以,word方面不是很好用,后来选择使用了docx4j,

    File file = new File(wordTempPath);
    InputStream in = new FileInputStream(file);
    WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(in);
    //获取word所有内容
    List<Object> list= wordMLPackage.getMainDocumentPart().getContent();
    //将文件中的内容分隔成每一道题
    List<Map<String, String>> questionMapList = getSubjectList(list);
    

    getSubjectList方法根据特定的规则将整段的信息分隔成片段

    /**
         * 将word中的题目分割成list<Object>放入List
         * @param list
         * @return
         */
        private List<Map<String, String>> getSubjectList(List<Object> list){
        	List<Map<String, String>> subjectList = new ArrayList<Map<String,String>>();
        	StringBuffer subjectItem =new StringBuffer();
        	int count =0;
        	int qNum = 0;
        	//划分题目
        	//以数字开头并且包含.表示一个新的题目开始
    		String regex = "^\\d{1,100}\\.";
    		Pattern pattern = Pattern.compile(regex);
    		Matcher m = null;
    		Map<String, String> tempMap = new HashMap<String, String>();
    		String qtype ="";
    		String oldQtype = "";
    		String line ="";
        	for (int i = 0; i < list.size(); i++) {
        		line = list.get(i).toString();
        		m = pattern.matcher(line);
        		if(m.find()){//题干
        			count++;
        			if(qNum>0){//不是文件文件第一个题干,将之前的buffer保存
        				tempMap = new HashMap<String, String>();
        				tempMap.put("qtype",oldQtype);
        				tempMap.put("content", subjectItem.toString());
        				subjectList.add(tempMap);
        				oldQtype=qtype;
        				subjectItem = new StringBuffer();
        				subjectItem.append(line);
        			}else{//文件第一个题干,创建新的buffer,并将题干放入buffer
        				subjectItem = new StringBuffer();
        				subjectItem.append(line);
        			}
        			qNum++;
        		}else if(line.startsWith("【单选题】")){
    				qtype = "1";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else if(line.startsWith("【多选题】")){
    				qtype = "2";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else if(line.startsWith("【判断题】")){
    				qtype = "3";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else if(line.startsWith("【不定项选择题】")){
    				qtype = "4";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else{
    				subjectItem.append(line);
        		}
        		List<String> resList = DocxUtils.getShortStr(subjectItem.toString());
        		/*if(i==list.size()-1){
        			tempMap = new HashMap<String, Object>();
    				tempMap.put("qtype",oldQtype);
    				tempMap.put("content", subjectItem.toString());
    				tempMap.put("imgMsgList", resList);
    				subjectList.add(tempMap);
        		}*/
    		}
        	return subjectList;
        }
    

    上述步骤完成之后需要将信息解析成具体的实体,然后再进行格式校验,如果格式校验正确那么最后再处理图片问题,毕竟图片处理之后需要上传到服务器,如果格式或者内容不符合导入要求,那么上传图片之后浪费资源;
    图片处理步骤:
    1.获取所有存在图片的题目的的标号
    word模板
    如上图所示,获取的编号为2
    2.根据题目编号将一个word文档切割成多个word文档,这样处理的原因是如果想要获取word中的图片信息,只找到一次性获取所有的图片信息的方法,那么就导致图片信息和题目无法对应上,也就是你获得了图片信息,但是你不知道是哪个题目的图片;所以将整个文档根据题目分割成多个word文档,再进行获取图片信息,那么两者就能对应上了;

    /**
    	 * 将word切割
    	 * @param in
    	 * @return
    	 * @throws Docx4JException
    	 */
    	 private void splitWord(HttpServletRequest request) throws Docx4JException{
    	    	InputStream in = null;
    			try {
    				in = new FileInputStream(new File(request.getSession().getAttribute("wordRootPath").toString()));
    			} catch (FileNotFoundException e) {
    				e.printStackTrace();
    			}
    	    	WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(in);
    	    	//获取word所有内容
    	    	List<Object> list= wordMLPackage.getMainDocumentPart().getContent();
    	    	WordprocessingMLPackage doc1 =null;
    	    	int count =0;
    	    	for (int i = 0; i < list.size(); i++) {
    	    		String tempFileName=null;
    	    		String regex = "^\\d{1,100}\\.";
    	    		Pattern pattern = Pattern.compile(regex);
    	    		Matcher m = pattern.matcher(list.get(i).toString());
    				if(m.find()){//判断当前内容是否为题干
    					count++;
    					if(count==1){//第一题开始
    						doc1 = WordprocessingMLPackage.createPackage();
    						doc1.getMainDocumentPart().addObject(list.get(i));
    					}else{//非第一题
    						tempFileName=count-1+"";
    						doc1.save(new File(request.getSession().getAttribute("wordUUIDFileName")+"/"+tempFileName+".docx"));
    						doc1 = WordprocessingMLPackage.createPackage();
    						doc1.getMainDocumentPart().addObject(list.get(i));
    					}
    				}else{
    					if(count>0){
    						doc1.getMainDocumentPart().addObject(list.get(i));
    					}
    				}
    				if(i==list.size()-1){
    					tempFileName=count+"";
    					doc1.save(new File(request.getSession().getAttribute("wordUUIDFileName")+"/"+tempFileName+".docx"));
    				}
    			}
    	    }
    

    在这里插入图片描述
    word中有5题,所以分隔成了5个文件,最后一个是用户上传的源文件;
    做到这里的时候觉得就快大功告成了,很开心,但是,打开一个切分后的子文件你就会发现,文件的图片只有位置不显示图片;
    在这里插入图片描述
    经过一番研究终于找到了原因:
    docx文件存储的本质是xml文件,其中图片的信息的存储是这样的,图片插入的位置是一个图片标签,这个标签里面有个对应的属性唯一标识一张图片,相当于html中标签的id属性,而所有的图片实际信息也就是二进制数据统一存储在文档的某个位置,然后标签中的id与其一一对应
    在这里插入图片描述
    在这里插入图片描述
    当你切分word文档的时候只是将图片标签信息切分过去了,但是实际的二进制数据并没有切分过去,所以导致打开切分后的word文件图片只有位置,不显示
    于是乎开动大脑,我在切分后的word文件中获取唯一标识,再到用户上传的源文件中获取二进制数据,哈哈哈,有点麻烦,但是我也很无奈啊;撸起袖子加油干!

    package com.mxexam.utils.question;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.xmlbeans.XmlCursor;
    import org.apache.xmlbeans.XmlObject;
    import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
    import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
    import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTObject;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
    
    import com.microsoft.schemas.vml.CTShape;
    /**
     * 获取2007word中的图片索引(例:Ird4,Ird5)
     * @author zcy
     *
     */
    public class XWPFUtils {
    
        //获取某一个段落中的所有图片索引
        public static List<String> readImageInParagraph(XWPFParagraph paragraph) {
            //图片索引List
            List<String> imageBundleList = new ArrayList<String>();
    
            //段落中所有XWPFRun
            List<XWPFRun> runList = paragraph.getRuns();
            for (XWPFRun run : runList) {
                //XWPFRun是POI对xml元素解析后生成的自己的属性,无法通过xml解析,需要先转化成CTR
                CTR ctr = run.getCTR();
                //对子元素进行遍历
                XmlCursor c = ctr.newCursor();
                //这个就是拿到所有的子元素:
                c.selectPath("./*");
                while (c.toNextSelection()) {
                    XmlObject o = c.getObject();
                    //如果子元素是<w:drawing>这样的形式,使用CTDrawing保存图片
                    if (o instanceof CTDrawing) {
                        CTDrawing drawing = (CTDrawing) o;
                        CTInline[] ctInlines = drawing.getInlineArray();
                        for (CTInline ctInline : ctInlines) {
                            CTGraphicalObject graphic = ctInline.getGraphic();
                            //
                            XmlCursor cursor = graphic.getGraphicData().newCursor();
                            cursor.selectPath("./*");
                            while (cursor.toNextSelection()) {
                                XmlObject xmlObject = cursor.getObject(); 
                                // 如果子元素是<pic:pic>这样的形式
                                if (xmlObject instanceof CTPicture) {
                                    org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture picture = (org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture) xmlObject;
                                    //拿到元素的属性
                                    imageBundleList.add(picture.getBlipFill().getBlip().getEmbed());
                                }
                            }
                        }
                    }
                    //使用CTObject保存图片
                    //<w:object>形式
                    if (o instanceof CTObject) {
                        CTObject object = (CTObject) o;
                        XmlCursor w = object.newCursor();
                        w.selectPath("./*");
                        while (w.toNextSelection()) {
                            XmlObject xmlObject = w.getObject();
                            if (xmlObject instanceof CTShape) {
                                CTShape shape = (CTShape) xmlObject;
                                /*imageBundleList.add(shape.getImagedataArray()[0].getId2());*/
                            }
                        }
                    }
                }
            }
            return imageBundleList;
        }
    }
    
    /**
    	 * 获取word中图片上传到文件服务器
    	 * @return
    	 * @throws FileNotFoundException 
    	 */
    	public static  List<Map<String,String>> getImgUrl(List<Map<String,String>> imgMsgList,HttpServletRequest request) throws Exception{
    		/* * 实现思路
    		 * 1、根据段落docx获取图片索引
    		 * 2、根据获取到的图片数据标识,在总的docx中获取图片data数据
    		 * 3.上传图片返回访问路径;*/
    		//未分割之前的总文件地址
    		ResourceBundle resource = ResourceBundle.getBundle("URL");
    		String imgLocalPath = resource.getString("imgLocalPath");
    		String Indexdocx =request.getSession().getAttribute("wordRootPath").toString();
            //读取总文件
    		InputStream in = new FileInputStream(Indexdocx);
            XWPFDocument xwpfDocumentIndex = new XWPFDocument(in);
            in.close();
            List<XWPFPictureData> list = xwpfDocumentIndex.getAllPackagePictures();
            //需要获取数据的图片名称
            String paraPicName = "";
            //总文档中的图片名称
            String pictureName ="";
            //上传到图片服务器之后的图片名称
            //图片索引rId1/rId2/rId3..
            String id ="";
            String uuidName = "";
            String endName = "";
            byte[] bd = null;
            //方法返回的List包含,题目序号,上传之后图片名称
            List<Map<String,String>> resMapList = new ArrayList<Map<String,String>>();
            Map<String, String> imgUploadNameMap = new HashMap<String,String>();
            for (XWPFPictureData xwpfPictureData : list) {
            	uuidName = UUID.randomUUID().toString();
            	id = xwpfPictureData.getParent().getRelationId(xwpfPictureData);
            	pictureName = xwpfPictureData.getFileName();
            	endName = pictureName.substring(pictureName.lastIndexOf("."));
            	bd = xwpfPictureData.getData();
            	FileOutputStream fos = new FileOutputStream(new File(imgLocalPath+uuidName+endName)); 
    	        fos.write(bd);
    	        fos.flush();
    	        fos.close();
    	        ImageSizer.imageZip(new File(imgLocalPath+uuidName+endName), new File(imgLocalPath+uuidName+"-e"+endName), "", 130, 130, 1);
    	        imgUploadNameMap.put(id, uuidName+endName);
    		}
            //遍历参数
            String tempPicName = "";
            String tempValue ="";
            for (Map<String, String> map : imgMsgList) {
            	tempPicName = map.get("pictureName");
            	tempValue = imgUploadNameMap.get(tempPicName);
            	if(tempValue!=null){
            		map.put("pictureName", tempValue);
            	}else{
            		map.put("pictureName", "");
            	}
            	resMapList.add(map);
    		}
    		return resMapList;
    	}
    

    最后上传之后的图片信息设置到对应的实体中再保存到数据库就OK了
    做到这里,本以为大功告,谁知长路漫漫,需求又改了!抹掉两行泪,将袖子撸起更高,加油!!!

    功能模块版本2

    新需求:题干和选项都要支持添加图片,而且位置不固定,需要识别一段文字中的多张图片的准确位置;
    本来想着从xml文件下手,研究很久,始终无果,后来得到一位技术大牛相助,指点迷津;思路是:将docx转换成html然后读取指定标签,就可以实现我的需求;大牛说的很笼统,但是改变了我思考的方向,实践证明,大牛见多识广果然厉害!话不多说,上码

    //1.将docx转换成HTML
    DocxUtils.docx2html( rootpath+"/"+userpath+"/"+newpath, rootpath+"/"+userpath+"/"+"root.html");
    //2.解析HTML,获取question字符串列表
    List<String> questionStringList = DocxUtils.readHTML(rootpath+"/"+userpath+"/"+"root.html");
    //3.解析字符串列表获取question信息列表
    List<Map<String, String>> questionList = DocxUtils.getQuestionsStrList(questionStringList);
    //4.解析上面列表,生成question实体及相关信息列表
    questionMsgList = getQuestions(questionList, request);
    //5.检查试题格式
    flag = checkQuestion(questionMsgList,request);
    //6.获取题目中的图片信息
    imgIndexList = DocxUtils.getShortStr(itemQuestion.getQcontent());
    //7.获取图片信息
    List<Map<String,Object>> imgMagList = getImgUrl(imgMsgMapList, request);
    //8.将图片信息设置到对应的试题中去			
    List<Questionoption> itemOptionList = new ArrayList<Questionoption>();
    				Map<String,String> imgMap = new HashMap<String,String>();
    				for (Map<String, Object> map : imgMagList) {
    					detailes = (int) map.get("details");
    					imgMap =  (Map<String, String>) map.get("imgIndexs");
    					itemQues = (Question) questionMsgList.get((Integer)map.get("qIndex")).get("question");
    					for (Entry<String, String> entry : imgMap.entrySet()) {
    						itemString2 = "&^&"+entry.getKey()+"&^&";
    						   if(detailes==666){//题干
    								itemString = itemQues.getQcontenttext().replace(itemString2, "<img src='"+imgLoadPath+entry.getValue()+"' style='max-width:50%'>");
    								itemQues.setQcontenttext(itemString);
    								itemString = itemQues.getQcontent().replace(itemString2, "");
    								itemQues.setQcontent(itemString);
    								questionMsgList.get((Integer)map.get("qIndex")).put("question",itemQues);
    						   }else if(detailes==999){//解析
    							   itemAnalysis = itemQues.getAnalysis();
    							   itemString = itemAnalysis.replace(itemString2, "<img src='"+imgLoadPath+entry.getValue()+"' style='max-width:50%'>");
    							   itemQues.setAnalysis(itemString);
    							   questionMsgList.get((Integer)map.get("qIndex")).put("question",itemQues);
    						   }else{
    							   itemOptionList = itemQues.getOptionList();
    							   itemString = itemOptionList.get(detailes).getOptdes().replace(itemString2, "<img src=\""+imgLoadPath+entry.getValue()+"\" style=\"max-width:50%\">");
    							   itemOptionList.get(detailes).setOptdes(itemString);
    							   itemOptionList = itemQues.getOptionList();
    							   itemQues.setOptionList(itemOptionList);
    							   questionMsgList.get((Integer)map.get("qIndex")).put("question",itemQues);
    						   }
    					}
    				}
    
    package com.mxexam.controller.question;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.docx4j.Docx4J;
    import org.docx4j.Docx4jProperties;
    import org.docx4j.convert.out.HTMLSettings;
    import org.docx4j.openpackaging.exceptions.Docx4JException;
    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
    import com.mxexam.entity.question.Question;
    import com.mxexam.entity.question.Questionoption;
    import com.mxexam.utils.question.DesUtil;
    
    import javassist.expr.NewArray;
    
    public class DocxUtils {
    	/**
    	 * 将docx转换成html
    	 * @param docx
    	 * @param html
    	 * @throws FileNotFoundException 
    	 * @throws Docx4JException 
    	 */
    	public static void docx2html(String docx,String html) throws FileNotFoundException, Docx4JException{
    		//1.生成的HTML文件需要提前创建好
    		File file = new File(html);
    		if(!file.exists()){
    			try {
    				file.createNewFile();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	 	WordprocessingMLPackage wordMLPackage= Docx4J.load(new java.io.File(docx));  
            HTMLSettings htmlSettings = Docx4J.createHTMLSettings();  
            String imageFilePath=html.substring(0,html.lastIndexOf("/")+1)+"/images";  
            htmlSettings.setImageDirPath(imageFilePath);  
            htmlSettings.setImageTargetUri( "images");  
            htmlSettings.setWmlPackage(wordMLPackage);  
            String userCSS = "html, body, div, span,font, h1, h2, h3, h4, h5, h6, p, a, img,  ol, ul, li, table, caption, tbody, tfoot, thead, tr, th, td " +  
                    "{ margin: 0; padding: 0; border: 0;}" +  
                    "body {line-height: 1;} ";  
              
            htmlSettings.setUserCSS(userCSS);  
            OutputStream os;  
            os = new FileOutputStream(html);  
            Docx4jProperties.setProperty("docx4j.Convert.Out.HTML.OutputMethodXML", true);  
            Docx4J.toHTML(htmlSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);  
    	}
    	/**
    	 * 读取HTML中文字内容和图片信息
    	 * @param HTMLPath
    	 * @return
    	 * @throws IOException 
    	 */
    	public static List<String> readHTML(String HTMLPath) throws IOException{
    		List<String> allList = new ArrayList<>();
        	File input = new File(HTMLPath);
        	Document doc = Jsoup.parse(input, "UTF-8", "");
        	Elements links = doc.select("span.2,img");
        	/*Elements links = doc.select("p,img");*/
        	String item = "";
        	boolean flag = false;
        	for (Element link : links) {
        		String itemContent = link.text();
        		if("【".equals(itemContent)){
        			flag = true;
        			item = item+itemContent;
        		}else{
        			if(flag){
            			item = item+itemContent;
            			if(itemContent.contains("】")){
            				allList.add(item);
            				item="";
            				flag = false;
            			}
            		}else{
            			allList.add(itemContent);
            		}
        		}
        		if(!"".equals(link.attr("id"))){
        			allList.add("&^&"+link.attr("id")+"&^&");
        		}
        	}
    		return allList;
    	}
    	/**
    	 * 去除listh中的重复数据
    	 * @param list
    	 * @return
    	 */
        public static List removeDuplicate(List list){  
            List listTemp = new ArrayList();  
            for(int i=0;i<list.size();i++){  
                if(!listTemp.contains(list.get(i))){  
                    listTemp.add(list.get(i));  
                }  
            }  
            return listTemp;  
        } 
        /**
         * 获取分隔后的question字符串列表
         * @param list
         * @return
         */
        public static List<Map<String, String>> getQuestionsStrList(List<String> list){
        	List<Map<String, String>> subjectList = new ArrayList<Map<String,String>>();
        	StringBuffer subjectItem =new StringBuffer();
        	int count =0;
        	int qNum = 0;
        	//划分题目
        	//以数字开头并且包含.表示一个新的题目开始
    		String regex = "^\\d{1,100}\\.";
    		Pattern pattern = Pattern.compile(regex);
    		Matcher m = null;
    		Map<String, String> tempMap = new HashMap<String, String>();
    		String qtype ="";
    		String oldQtype = "";
    		String line ="";
        	for (int i = 0; i < list.size(); i++) {
        		line = list.get(i).toString();
        		m = pattern.matcher(line);
        		if(m.find()){//题干
        			count++;
        			if(qNum>0){//不是文件文件第一个题干,将之前的buffer保存
        				tempMap = new HashMap<String, String>();
        				tempMap.put("qtype",oldQtype);
        				tempMap.put("content", subjectItem.toString());
        				subjectList.add(tempMap);
        				oldQtype=qtype;
        				subjectItem = new StringBuffer();
        				subjectItem.append(line);
        			}else{//文件第一个题干,创建新的buffer,并将题干放入buffer
        				subjectItem = new StringBuffer();
        				subjectItem.append(line);
        			}
        			qNum++;
        		}else if(line.startsWith("【单选题】")){
    				qtype = "1";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else if(line.startsWith("【多选题】")){
    				qtype = "2";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else if(line.startsWith("【判断题】")){
    				qtype = "3";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else if(line.startsWith("【不定项选择题】")){
    				qtype = "4";
    				if(count==0){
    					oldQtype=qtype;
    				}
    			}else{
    				subjectItem.append(line);
        		}
        		if(i==list.size()-1){
        			tempMap = new HashMap<String, String>();
    				tempMap.put("qtype",oldQtype);
    				tempMap.put("content", subjectItem.toString());
    				subjectList.add(tempMap);
        		}
    		}
        	return subjectList;
        }
        /**
         * 获取字符串中所有的子串的位置
         * @param str
         * @return
         */
        public static String getAllSonstrIndex(String str,String sonStr){
        	StringBuffer buffer = new StringBuffer();
        	int index = str.indexOf(sonStr);
        	while(index!=-1){
        		buffer.append(index+",");
        		index = str.indexOf(sonStr,index+1);
        	}
        	String string = buffer.toString();
        	if(string.indexOf(",")!=-1){
        		string = string.substring(0, string.lastIndexOf(","));
        	}
        	return string;
        }
        /**
         * 获取图片地址列表
         * @param str:总的字符串
         * @return
         */
        public static List<String> getShortStr(String str){
        	List<String> resList = new ArrayList<String>();
        	String indexsStr = getAllSonstrIndex(str,"&^&");
        	String[] indexs = indexsStr.split(",");
        	int start = 0;
        	int end = 0;
        	for (int i = 0; i < indexs.length-1; i=i+2) {
    			start=Integer.parseInt(indexs[i]);
    			end=Integer.parseInt(indexs[i+1]);
    			resList.add(str.substring(start+3,end));
    		}
        	return resList;
        }
    }
    
    

    好了,本人开发小白,不对的或者不好的地方望大家批评指正,不清楚的地方欢迎加微信学习讨论,但拒绝恶意吐槽哦!!!
    觉得内容对您有帮助,欢迎打赏哦!!!嘻嘻嘻!!!

    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • java解析pdf

    添加spire.pdf依赖,依赖需要下载到本地仓库

    <repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>
    
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>2.2.0</version>
    </dependency>
    public static void main(String[] args) {
        try {
            PdfDocument doc = new PdfDocument();
            doc.loadFromFile("C:\\TTT\\test\\day01.pdf");
            StringBuilder sb = new StringBuilder();
            PdfPageBase page;
            for (int i = 0; i < doc.getPages().getCount(); i++) {
                //获取每一行的page对象
                page = doc.getPages().get(i);
                sb.append(page.extractText(true));
                // 这个if中是图片的解析输出
                if (page.extractImages() != null) {
                    for (BufferedImage image : page.extractImages()) {
                        if (image != null) {
                            //指定输出图片名,指定图片格式,后缀自己换
                            File output = new File("C:\\TTT\\test\\copy\\a.png");
                            ImageIO.write(image, "PNG", output);
                        }
                    }
                }
            }
            System.out.println(sb);
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    }
    展开全文
  • java读取图片文字

    千次阅读 2019-12-19 11:05:29
    java自动读取图片文字信息代码片工具类 java中识别文字使用的软件是tesseractocr(使用的版本是3.02,3以后的版本才支持中文),这个软件需要安装在本地电脑中,安装的过程中全部都按照默认进行安装(以便于Java...

    java自动读取图片文字信息


    java中识别文字使用的软件是tesseractocr(使用的版本是3.02,3以后的版本才支持中文),这个软件需要安装在本地电脑中,安装的过程中全部都按照默认进行安装(以便于Java直接调用),
    想要完整的程序私信我或者直接下载https://download.csdn.net/download/qq_35571894/12040072 ,打包下载完成后导入即可运行测试。
    另外想要读取PDF文件信息的请点击链接:https://download.csdn.net/download/qq_35571894/12038360 spireOCR 可以识别PDF上文字信息

    代码片

    代码片.

    public class ImageIOHelper {
        //设置语言
        private Locale locale = Locale.CHINESE;
        //自定义语言构造的方法
        public ImageIOHelper(Locale locale){
            this.locale=locale;
        }
        //默认构造器Locale.CHINESE
        public ImageIOHelper(){
        }
        /**
         * 创建临时图片文件防止损坏初始文件
         * @param imageFile
         * @param imageFormat like png,jps .etc
         * @return TempFile of Image
         */
        public File createImage(File imageFile, String imageFormat) throws IOException {
    
            //读取图片文件
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(imageFormat);
            ImageReader reader = readers.next();
            //获取文件流
            ImageInputStream iis = ImageIO.createImageInputStream(imageFile);
            reader.setInput(iis);
            IIOMetadata streamMetadata = reader.getStreamMetadata();
    
            //设置writeParam
            TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.CHINESE);
            tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED); //设置可否压缩
            //获得tiffWriter和设置output
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("tiff");
            ImageWriter writer = writers.next();
    
    
            BufferedImage bi = reader.read(0);
            IIOImage image = new IIOImage(bi,null,reader.getImageMetadata(0));
            File tempFile = tempImageFile(imageFile);
            ImageOutputStream ios = ImageIO.createImageOutputStream(tempFile);
    
            writer.setOutput(ios);
            writer.write(streamMetadata, image, tiffWriteParam);
    
            ios.close();
            iis.close();
            writer.dispose();
            reader.dispose();
    
            return tempFile;
        }
        /**
         * 给tempfile添加后缀
         * @param imageFile
         * @throws IOException
         */
        private File tempImageFile(File imageFile) throws IOException {
            String path = imageFile.getPath();
            StringBuffer strB = new StringBuffer(path);
            strB.insert(path.lastIndexOf('.'),"_text_recognize_temp");
            String s=strB.toString().replaceFirst("(?<=//.)(//w+)$", "tif");
            Runtime.getRuntime().exec("attrib "+"\""+s+"\""+" +H"); //设置文件隐藏
            return new File(strB.toString());
        }
    
    

    工具类

    package utils;
    
    import controller.ImageIOHelper;
    import org.jdesktop.swingx.util.OS;
    
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Locale;
    
    public class OCRUtil {
    
        private final String LANG_OPTION = "-l";  //英文字母小写l,并非阿拉伯数字1
        private final String EOL = System.getProperty("line.separator");
        private String tessPath = "D://Tesseract//Tsseract-OCR//Tesseract-OCR";//ocr的安装路径
    
        public OCRUtil(String tessPath,String transFileName){
            this.tessPath=tessPath;
        }
    
        //OCRUtil的构造方法,默认路径是"C://Program Files (x86)//Tesseract-OCR"
        public OCRUtil(){     }
    
        public String getTessPath() {
            return tessPath;
        }
        public void setTessPath(String tessPath) {
            this.tessPath = tessPath;
        }
        public String getLANG_OPTION() {
            return LANG_OPTION;
        }
        public String getEOL() {
            return EOL;
        }
    
        /**
         * @param imageFile 需要识别的文件
         * @param imageFormat 文件的格式
         * @return
         * @throws Exception
         */
        public String recognizeText(File imageFile,String imageFormat)throws Exception{
            File tempImage = new ImageIOHelper().createImage(imageFile,imageFormat);
            return ocrImages(tempImage, imageFile);
        }
    
        //可以自定义语言
        public String recognizeText(File imageFile, String imageFormat, Locale locale)throws Exception{
            File tempImage = new ImageIOHelper(locale).createImage(imageFile,imageFormat);
            return ocrImages(tempImage, imageFile);
        }
    
        /**
         * @param tempImage 临时文件
         * @param imageFile 需要识别的文件
         * @return 识别后的内容
         * @throws IOException
         * @throws InterruptedException
         */
        private String ocrImages(File tempImage,File imageFile) throws IOException, InterruptedException{
    
            //设置输出文件的保存的文件目录,以及文件名
            File outputFile = new File(imageFile.getParentFile(),"test");
            StringBuffer strB = new StringBuffer();
    
            //设置命令行内容
            List<String> cmd = new ArrayList<String>();
            if(OS.isWindowsXP()){
                cmd.add(tessPath+"//tesseract");
            }else if(OS.isLinux()){
                cmd.add("tesseract");
            }else{
                cmd.add(tessPath+"//tesseract");
            }
            cmd.add("");
            cmd.add(outputFile.getName());
            cmd.add(LANG_OPTION);
            cmd.add("chi_sim");//中文包
            cmd.add("equ");//常用数学公式包
            cmd.add("eng");//英语包
    
    
            //创建操作系统进程
            ProcessBuilder pb = new ProcessBuilder();
            pb.directory(imageFile.getParentFile());//设置此进程生成器的工作目录
            cmd.set(1, tempImage.getName());
            pb.command(cmd);//设置要执行的cmd命令
            pb.redirectErrorStream(true);//设置后续子进程生成的错误输出都将与标准输出合并
    
            long startTime = System.currentTimeMillis();
            System.out.println("开始时间:" + startTime);
    
            Process process = pb.start();//开始执行,并返回进程实例
            //最终执行命令为:tesseract 1.png test -l chi_sim+equ+eng
    
            int w = process.waitFor();
            tempImage.delete();//删除临时正在工作文件
            if(w==0){ // 0代表正常退出
                BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()+".txt"),"UTF-8"));
                String str;
                while((str = in.readLine())!=null){
                    strB.append(str).append(EOL);
                }
                in.close();
    
                long endTime = System.currentTimeMillis();
                System.out.println("结束时间:" + endTime);
                System.out.println("耗时:" + (endTime - startTime) + "毫秒");
    
            }else{
                String msg;
                switch(w){
                    case 1:
                        msg = "Errors accessing files.There may be spaces in your image's filename.";
                        break;
                    case 29:
                        msg = "Cannot recongnize the image or its selected region.";
                        break;
                    case 31:
                        msg = "Unsupported image format.";
                        break;
                    default:
                        msg = "Errors occurred.";
                }
                tempImage.delete();
                throw new RuntimeException(msg);
            }
            new File(outputFile.getAbsolutePath()+".txt");//.delete();
            return strB.toString().replaceAll("\\s*", "");
        }
    }
    
    
    展开全文
  • ORC工具解析图片文字

    千次阅读 2016-10-20 15:53:08
    看到好多人使用ORC解析图片,感觉准确率不是很高,但是网上都讲的比较复杂,我的理解就是两步。 安装工具、调用工具1.解析工具下载 里面包含 ORC3.0安装包以及中文库,另附带两个jar包用于图形处理,此工具为绿色...

    看到好多人使用ORC解析图片,感觉准确率不是很高,但是网上都讲的比较复杂,我的理解就是两步。
    安装工具、调用工具

    1.解析工具下载
    里面包含 ORC3.0安装包以及中文库,另附带两个jar包用于图形处理,此工具为绿色版
    http://download.csdn.net/detail/xiekuntarena/9659084
    安装完毕之后,需要将中文库chi_sim.traineddata复制到tessdata文件夹下

    2.CMD命令实现调用
    解析的图片与放置的路径如下图:
    这里写图片描述
    需解析的图片已放置在ORC目录下

    CMD执行:D:/Tesseract-OCR/tesseract D:/Tesseract-OCR/3.PNG D:/Tesseract-OCR/3 -l chi_sim

    第一个参数:tesseract为ORC的执行exe
    第二个参数:图片的路径
    第三个参数:生成结果的文件地址,默认格式为.txt
    第四个参数:-l (L) chi_sim 表示使用中文库解析

    3.JAVA代码实现

    package testcase;
    import java.io.IOException;
    public class TestCase {
        public static void main(String[] args) {
            try {
                String strCmd = 
     "D:/Tesseract-OCR/3.PNG " + 
     "D:/Tesseract-OCR/3 "+
     "-l chi_sim";
                System.out.println(strCmd);
                Runtime.getRuntime().exec(strCmd);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    执行结果如下图:
    这里写图片描述
    可看出,关注–》关汪 解析的不准确

    可通过对图片进行拉伸、翻转、缩放、明暗、灰度,将每一种图片进行解析并得出结果,取多次解析结果进行分析。具体怎么做,大家可以研究研究。

    展开全文
  • java解析PDF

    千次阅读 2019-08-05 15:48:28
    java解析PDF文件(汉字及图片) 在工程需求中如何处理java解析pdf文件。 首先准备jar包:Spire.Pdf.jar,本人使用的是2.6.3版本。 1、解析pdf文字格式: public static String ExportPDFUtil(String fileName) ...
  • 更多的人是想先实现后理解吧,在这里有一个重要的东西叫做驯化文件目录,少了这个东西的话就很不好操作,话不多说,上代码,首先上场的是解析pdf为图片并保存至自定义文件夹中` PdfDocument doc = new PdfDocument...
  • java解析word,图片

    千次阅读 2018-06-29 16:12:22
    将word转换为xml,根据xml的标签,解析内容,从而解析出word里面的文字图片。 public class ReadWord2 { Element resultNode = null; boolean isFound = false; String topoPicId= ""; String ...
  • java图片文字自动识别

    千次阅读 2018-09-24 01:54:57
    下载该软件需要配置环境变量,通过环境变量在dos命令下进行相关图片文字解析操作,为了使程序更加简单,采用tess4j包去实现。 步骤一: 下载包(此处我采用后者):阿里云maven仓库 或者 创建maven项目在pom.xml中...
  • Apache PDFBox是一个开源Java库,支持PDF文档的开发和转换。 我们可以使用PDFBox开发可以创建,转换和操作PDF文档的Java程序。PDFBox的主要功能: Extract Text - 使用PDFBox,您可以从PDF文件中提取Unicode文本。 ...
  • java解析pdf获取pdf中内容信息

    万次阅读 多人点赞 2019-04-28 18:31:13
    java解析pdf获取pdf中内容信息 今日项目中需要将pdf中的数据获取到进行校验数据,于是前往百度翻来覆去找到以下几种办法,做个笔记,方便日后查询。 1 使用开源组织提供的开源框架 pdfbox api ; ...
  • 其实公司之前的产品已经使用.net实现过此功能,不过现在公司全面转型Java,我们也要研究出一个适用Java的解决方案。 office文档中的公式编辑器 mathtype插件 mathtype是一个第三方的数学公式插件,它能在
  • 首先先放一篇Android 上传文件,图片。以及服务器端接收相关的内容 原文链接:http://www.2cto.com/kf/201311/258685.html 我们做web开发的时候几乎都是通过一个表单来实现上传。并且是post的方式。而且都必须要加个...
  • 一、使用tesseract-ocr  1. https://github.com/tesseract-ocr/tesseract/wiki上...  window64位安装包:tesseract-ocr-w64-setup-v4.1.0.20190314.exe  简体中文训练文件:chi_sim.traineddata 约40M  2.... 3....
  • Java调用百度OCR文字识别API实现图片文字识别软件

    千次阅读 多人点赞 2019-01-06 13:35:59
    Java调用百度OCR文字识别API实现图片文字识别软件 这是一款小巧方便,强大的文字识别软件,由Java编写,配上了窗口界面 调用了百度ocr文字识别API 识别精度高。 打包生成了jar可执行程序 完整项目GitHub地址 ...
  • java解析pdf格式文件获取文本内容

    千次阅读 2019-11-05 18:34:10
    思路:先将pdf按照页数分割成图片,在将分割的图片图片识别,提取文字,最后将提取到的文字解析或者保存到txt文件。 图片识别我使用的是百度开发者中心提供的图片识别接口,我在上一篇文章中有详细说明,这里直接...
  • JAVA解析RTF 文件

    千次阅读 2016-09-14 17:35:38
    rtf文件 也称富文本格式(Rich Text Format, 一般简称为RTF),意为多文本格式是由微软公司开发的跨平台文档格式。... 通过java进行读取操作时,需要注意的是项目和文件的编码格式问题,本次测试的项目
  • 前段时间,为了解析PDF,花了不少时间去学习PDFbox和itext,这两个都是处理PDF的开源库,有java和C#的。作为一个刚开始学习这两个开源库的,感觉百度上的资源还是太少了。我做的是一个关于PDF的处理,在百度上找了...
  • java识别图片中的文字

    万次阅读 2018-04-27 10:47:12
    该方法只是一个测试,识别出来的文字与实际的文字会有差异 1.新建一个javaweb项目 ...3.新建类:import java.util.HashMap; import org.json.JSONObject; import com.baidu.aip.ocr.AipOcr; public...
  • Java批量解析微信dat文件,微信图片破解

    万次阅读 多人点赞 2019-07-11 15:50:58
    Java批量解析微信dat文件前言关于异或值怎么计算代码 前言 偶然看到有可以解密微信dat的文档,上网查了查,找到了一篇可以用的文章,不过转换过程代码是有问题的,在这里改了下发布上来。 参考地址:...
  •  * 添加 底部图片文字  * @param source 图片源  * @param declareText 文字本文  */  private static void addFontImage(BufferedImage source, String declareText) {  BufferedImage textImage = ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,368
精华内容 12,147
关键字:

java解析图片文字

java 订阅