一、前言

工作中,经常会碰到需要对word的处理操作,最最最常用的是word文档的导出,而且经常碰到各种抓脑壳的复杂格式的word,最开始我用的是poi,但是挣扎了一段时间,莫得法,换成了用docx4j,很强大,嗯,我喜欢,用了好长一段时间,发现网上关于docx4j的中文文档还是太少了,大家都是零零碎碎的一些博客文章。觉得,应该整理共享一下,让更多的人,享受到docx4j的便利。

引用官网上的一段话:docx4j是一个开源(ASLv2)Java库,用于创建和处理Microsoft Open XML(Word docx,Powerpoint pptx和Excel xlsx)文件。

二、理解docx文件

1.认识Open XML

docx4j主要是针对docx文件进行操作,操作的对象的Microsoft Open XML文件。

什么是Microsoft Open XML?

Office Open XML,也称为OpenXML或OOXML,是Office文档的基础XML的格式,应用于word,execl,ppt,图表等。该规范由Microsoft开发,被ISO和IEC采纳。现在是所有Microsoft Office文档(.docx,.xlsx和.pptx)的默认格式。

2.docx文件的结构

docx我们可以理解为一个前端项目的压缩包,里面有样式文件,dom格式的xml文件,我们解压一个docx的文件看一下它的目录结构:

我们先看根目录下的[Content_Types] .xml文件,这个是整个docx文件的内容组件的配置文件,整个压缩包中用到的文件都在里面配置,可以简单理解为,我们写前端时html文件的head部分关于js,css引用的部分,但这样理解有点不明确,想象一下,jsp文件include各部分的总页面,有点类似。

_rels这个目录是配置定义各部分间的关系,了解就行,

看里面的核心word目录,可以看到,这个目录结构跟我们前端项目的html、css结构很相似,

media目录下放多媒体元素,图片之类的,了解就行

theme目录,顾名思义,word的主题,了解就行

word目录下最重要的是里面的document.xml文件

其他的word部分文件,settings.xml和styles.xml是docx文件都有的配置和样式文件,footTable是字体表,footnotes是词汇表,其他的还有foot开头的脚表,head开头的是页眉文件之类的文件

3.docx的核心OpenXML文件格式

我们主要看document.xml文件,这个文件是整个docx的骨架,类似于前端页面的html文件,是最基础、也是最重要的文件。

理解document.xml的文本结构,这个文本结构类似html格式

(写到这突然有点不想写了.....,下面就随便记录哈了)

三、使用docx4j

1.使用的jar

maven导入

org.docx4j

docx4j

6.1.2

2.工具类

package com.zb.hello.util;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import javax.xml.bind.JAXBElement;

import javax.xml.bind.JAXBException;

import org.docx4j.XmlUtils;

import org.docx4j.dml.wordprocessingDrawing.Inline;

import org.docx4j.jaxb.XPathBinderAssociationIsPartialException;

import org.docx4j.openpackaging.exceptions.Docx4JException;

import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;

import org.docx4j.wml.ContentAccessor;

import org.docx4j.wml.Drawing;

import org.docx4j.wml.ObjectFactory;

import org.docx4j.wml.P;

import org.docx4j.wml.R;

import org.docx4j.wml.Tbl;

import org.docx4j.wml.Tc;

import org.docx4j.wml.Text;

import org.docx4j.wml.Tr;

public class Docx4jUtil {

public static Builder Builder;

public static Builder of(String path) throws FileNotFoundException, Docx4JException {

return new Builder(path);

}

public static class Builder {

private WordprocessingMLPackage template = null;

private Iterator texts = null;

// 占位符参数map

private Map params = new HashMap<>();

private Builder(String path) throws FileNotFoundException, Docx4JException {

if (path != null && !path.isEmpty()) {

this.template = WordprocessingMLPackage.load(new FileInputStream(new File(path)));

this.texts = getAllPlaceholderElementFromObject(template.getMainDocumentPart()).iterator();

}

}

/**

* 增加文本占位符参数(一个)

*

* @param key 键

* @param value 值

* @return Builder对象

*/

public Builder addParam(String key, String value) {

Builder builder = this;

if (key != null && !key.isEmpty()) {

/*while (texts.hasNext()) {

Text text = texts.next();

String temp = text.getValue();

if (temp.equals("${" + key + "}")) {

text.setValue(value);

texts.remove();

return builder;

}

}*/

params.put(key, value);

}

return builder;

}

/**

* 增加参数(多个)

*

* @param params 多个参数的map

* @return Builder对象

*/

public Builder addParams(Map params) {

this.params = params;

return this;

}

/**

* 增加一个表格

*

* @param tablePlaceholder 寻找表格的占位符

* @param placeholderRows 模板行所占行数

* @param list 替换模板占位符的数据

* @return Builder对象

* @throws JAXBException JAXBException

* @throws Docx4JException Docx4JException

*/

public Builder addTable(String tablePlaceholder, int placeholderRows, List> list)

throws Docx4JException, JAXBException {

List tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

Tbl tempTable = getTemplateTable(tables, tablePlaceholder);

if (tempTable != null && list != null && !list.isEmpty()) {

List trs = getAllElementFromObject(tempTable, Tr.class);

int rows = trs.size();

if (rows > placeholderRows) {

List

tempTrs = new ArrayList<>();

for (int i = rows - placeholderRows; i < rows; i++) {

tempTrs.add((Tr) trs.get(i));

}

for (Map trData : list) {

for (Tr tempTr : tempTrs) {

addRowToTable(tempTable, tempTr, trData);

}

}

for (Tr tempTr : tempTrs) {

tempTable.getContent().remove(tempTr);

}

}

}

return this;

}

private void loadImg(Tbl tempTable, byte[] decodeBuffer, int maxWidth) {

Inline inline = createInlineImage(template, decodeBuffer, maxWidth);

P paragraph = addInlineImageToParagraph(inline);

List rows = getAllElementFromObject(tempTable, Tr.class);

Tr tr = (Tr) rows.get(0);

List cells = getAllElementFromObject(tr, Tc.class);

Tc tc = (Tc) cells.get(0);

tc.getContent().clear();

tc.getContent().add(paragraph);

}

/**

* 通过站位符确定加载图片的位置,图片的位置为表格

*

* @param placeholder 占位符

* @param decodeBuffer 图片的字节流

* @return 当前对象

* @throws Docx4JException Docx4JException

* @throws JAXBException JAXBException

*/

public Builder addImg(String placeholder, byte[] decodeBuffer) throws Docx4JException, JAXBException {

addImg(placeholder, decodeBuffer, 0);

return this;

}

/**

* 通过站位符确定加载图片的位置,图片的位置为表格

*

* @param placeholder 占位符

* @param decodeBuffer 图片的字节流

* @param maxWidth 图片的最多宽度,不传默认写入图片原始宽度

* @return 当前对象

* @throws Docx4JException Docx4JException

* @throws JAXBException JAXBException

*/

public Builder addImg(String placeholder, byte[] decodeBuffer, int maxWidth) throws Docx4JException, JAXBException {

List tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

Tbl tempTable = getTemplateTable(tables, placeholder);

loadImg(tempTable, decodeBuffer, maxWidth);

return this;

}

/**

* 通过int的位置数组确定加载图片的位置,图片的位置为表格(以主界面为基准)

*

* @param wz int型数组,长度必须为3 ,第一个值为第几个表格,第二个值为第几行,第三个参数为第几个单元格

* @param decodeBuffer 图片的字节流

* @param maxWidth 图片的最多宽度,不传默认写入图片原始宽度

* @return 当前对象

*/

public Builder addImg(int[] wz, byte[] decodeBuffer, int maxWidth) {

Tc tc = getTcByWz(wz);

Tbl tempTable = (Tbl) getAllElementFromObject(tc, Tbl.class).get(0);

loadImg(tempTable, decodeBuffer, maxWidth);

return this;

}

/**

* 通过int的位置数组确定加载图片的位置,图片的位置为表格(以主界面为基准)

*

* @param wz int型数组,长度必须为3 ,第一个值为第几个表格,第二个值为第几行,第三个参数为第几个单元格

* @param decodeBuffer 图片的字节流

* @return 当前对象

*/

public Builder addImg(int[] wz, byte[] decodeBuffer) {

addImg(wz, decodeBuffer, 0);

return this;

}

/**

* 添加段落

*

* @param list 数据集合

* @param wz 模板段落所在的位置,长度为三(第几个表格,第几行,第几个单元格)

* @return Builder对象

*/

public Builder addParagrash(List> list, int[] wz) {

Tc tc = getTcByWz(wz);

List paraList = getAllElementFromObject(tc, P.class);

tc.getContent().clear();

for (Map item : list) {

paraList.forEach((tempPara) -> {

P workingPara = (P) XmlUtils.deepCopy(tempPara);

repaleTexts(workingPara, item);

tc.getContent().add(workingPara);

});

}

return this;

}

/**

* 移除含有占位符的Tr

* @param placeholder 占位符

* @return Builder对象

*/

public Builder removeTrByPlaceholder(String placeholder) {

//这种方式获取是正常的,但是get()方法操作的时候不能正常替换文本了。

//List trs = template.getMainDocumentPart().getJAXBNodesViaXPath("//w:tr", true);

List trs = getAllElementFromObject(template.getMainDocumentPart(), Tr.class);

Tr tr = (Tr) getTemplateObj(trs,placeholder,false);

if(tr != null){

Tbl tbl = (Tbl) tr.getParent();

tbl.getContent().remove(tr);

}

return this;

}

/**

* 移除含有占位符的Tr

* @param placeholders 占位符的集合

* @return Builder对象

*/

public Builder removeTrByPlaceholder(List placeholders) {

/* List trs = template.getMainDocumentPart().getJAXBNodesViaXPath("//w:tr", true);*/

List trs = getAllElementFromObject(template.getMainDocumentPart(), Tr.class);

List list = getTemplateObjs(trs,placeholders);

for (Object o:list) {

Tr tr = (Tr) o;

if(tr != null){

Tbl tbl = (Tbl) tr.getParent();

tbl.getContent().remove(tr);

}

}

return this;

}

/**

* 获取文件字节流

*

* @return 文件字节流

* @throws Docx4JException docx异常

*/

public byte[] get() throws Docx4JException {

if (!params.isEmpty()) {

while (texts.hasNext()) {

Text text = texts.next();

String temp = text.getValue();

for (Entry param : params.entrySet()) {

if (temp.equals("${" + param.getKey() + "}")) {

text.setValue(param.getValue());

}

}

}

}

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

template.save(outputStream);

return outputStream.toByteArray();

}

/**

* 获取指定单元格

*

* @param temp 模板段落所在的位置,长度为三(第几个表格,第几行,第几个单元格)

* @return tc

*/

private Tc getTcByWz(int[] temp) {

List tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

Tbl wzTable = (Tbl) tables.get(temp[0]);

Tr tr = (Tr) getAllElementFromObject(wzTable, Tr.class).get(temp[1]);

return (Tc) getAllElementFromObject(tr, Tc.class).get(temp[2]);

}

}

/**

* 创建包含图片的一个内联对象

*

* @param wordMLPackage WordprocessingMLPackage

* @param bytes 图片字节流

* @param maxWidth 最大宽度

* @return 图片的内联对象

*/

private static Inline createInlineImage(WordprocessingMLPackage wordMLPackage, byte[] bytes, int maxWidth) {

Inline inline = null;

try {

BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);

int docPrId = 1;

int cNvPrId = 2;

if (maxWidth > 0) {

inline = imagePart.createImageInline("Filename hint", "Alternative text", docPrId, cNvPrId, false, maxWidth);

} else {

inline = imagePart.createImageInline("Filename hint", "Alternative text", docPrId, cNvPrId, false);

}

} catch (Exception e) {

e.printStackTrace();

}

return inline;

}

/**

* 创建一个对象工厂并用它创建一个段落和一个可运行块R. 然后将可运行块添加到段落中. 接下来创建一个图画并将其添加到可运行块R中. 最后我们将内联

* 对象添加到图画中并返回段落对象.

*

* @param inline 包含图片的内联对象.

* @return 包含图片的段落

*/

private static P addInlineImageToParagraph(Inline inline) {

// 添加内联对象到一个段落中

ObjectFactory factory = new ObjectFactory();

P paragraph = factory.createP();

R run = factory.createR();

paragraph.getContent().add(run);

Drawing drawing = factory.createDrawing();

run.getContent().add(drawing);

drawing.getAnchorOrInline().add(inline);

return paragraph;

}

// 发现docx文档包含占位符的文本节点

private static List getAllPlaceholderElementFromObject(Object obj) {

List result = new ArrayList<>();

Class toSearch = Text.class;

Text textPlaceholder;

if (obj instanceof JAXBElement) {

obj = ((JAXBElement>) obj).getValue();

}

if (obj.getClass().equals(toSearch)) {

textPlaceholder = (Text) obj;

if (isPlaceholder(textPlaceholder.getValue())) {

result.add((Text) obj);

}

} else if (obj instanceof ContentAccessor) {

List> children = ((ContentAccessor) obj).getContent();

for (Object child : children) {

result.addAll(getAllPlaceholderElementFromObject(child));

}

}

return result;

}

// 发现docx文档中的节点

private static List getAllElementFromObject(Object obj, Class> toSearch) {

List result = new ArrayList<>();

if (obj instanceof JAXBElement) {

obj = ((JAXBElement>) obj).getValue();

}

if (obj.getClass().equals(toSearch)) {

result.add(obj);

} else if (obj instanceof ContentAccessor) {

List> children = ((ContentAccessor) obj).getContent();

for (Object child : children) {

result.addAll(getAllElementFromObject(child, toSearch));

}

}

return result;

}

// 这个方法只是查看表格是否含有我们的占位符,如果有则返回表格

private static Tbl getTemplateTable(List tables, String templateKey) {

return (Tbl) getTemplateObj(tables,templateKey,false);

}

/**

* 这个方法只是查看dom是否含有我们的占位符,如果有则返回dom

*

* @param objects 需要查找的dom元素

* @param placeholder 占位符

* @param f 是否全部查找,为ture时全部查找,返回的是list,为false时一找到元素就返回,只是单个元素

* @return 找到的元素

*/

private static Object getTemplateObj(List objects, String placeholder, boolean f) {

List objectList = new ArrayList<>();

for (Object o : objects) {

List> textElements = getAllElementFromObject(o, Text.class);

for (Object text : textElements) {

Text textElement = (Text) text;

if (textElement.getValue() != null && textElement.getValue().equals("${" + placeholder + "}")) {

if (!f) {

return o;

} else {

objectList.add(o);

}

}

}

}

return objectList.isEmpty()?null:objectList;

}

/**

* 这个方法只是查看dom是否含有我们的占位符,如果有则返回dom

* @param objects 需要查找的dom元素的集合

* @param placeholders 占位符集合

* @return 找到的元素的集合

*/

private static List getTemplateObjs(List objects, List placeholders) {

List objectList = new ArrayList<>();

for (Object o : objects) {

List> textElements = getAllElementFromObject(o, Text.class);

for (Object text : textElements) {

Text textElement = (Text) text;

if (textElement.getValue() != null && placeholders.contains(getPlaceholderStr(textElement.getValue()))) {

objectList.add(o);

}

}

}

return objectList;

}

/**

* 复制模板行

*

* @param reviewtable 表格

* @param templateRow 模板行

* @param replacements 填充模板行的数据

*/

private static void addRowToTable(Tbl reviewtable, Tr templateRow, Map replacements) {

Tr workingRow = XmlUtils.deepCopy(templateRow);

repaleTexts(workingRow, replacements);

reviewtable.getContent().add(workingRow);

}

/**

* 把工作对象中的全部占位符都替换掉

*

* @param working 工作对象

* @param replacements map数据对象

*/

private static void repaleTexts(Object working, Map replacements) {

List> textElements = getAllElementFromObject(working, Text.class);

for (Object object : textElements) {

Text text = (Text) object;

String keyStr = getPlaceholderStr(text.getValue());

if (keyStr != null && !keyStr.isEmpty()) {

String replacementValue = replacements.get(keyStr);

if (replacementValue != null) {

text.setValue(replacementValue);

} else {

text.setValue("--");

}

}

}

}

/**

* 判断字符串是否有${}占位符

*

* @param str 需要判断的字符串

* @return 是否字符串是否有${}占位符

*/

private static boolean isPlaceholder(String str) {

if (str != null && !str.isEmpty()) {

Pattern pattern = Pattern.compile("([$]\\{\\w+\\})");

Matcher m = pattern.matcher(str);

return m.find();

}

return false;

}

/**

* 得到占位符${}中的文本

*

* @param str 需要判断的字符串

* @return 占位符${}中的文本

*/

private static String getPlaceholderStr(String str) {

if (str != null && !str.isEmpty()) {

Pattern p = Pattern.compile("\\$\\{(.*?)\\}");

Matcher m = p.matcher(str);

if (m.find()) {

return m.group(1);//m.group(0)包括这两个字符

}

}

return null;

}

}

3.导出word文件使用

public byte[] downloadWord() throws Docx4JException, JAXBException, FileNotFoundException {

//模板文件路径

String path = this.getClass().getClassLoader().getResource("template/test.docx").getPath();

//模板中要生成表格的数据

List> list = new ArrayList<>();

for (int i = 0; i < 3; i++) {

Map m = new HashMap<>();

m.put("name", "姓名"+i);

m.put("sex", "性别"+i);

m.put("age", "年龄"+i);

m.put("bz", "备注"+i);

m.put("xx", "详细"+i);

list.add(m);

}

list.stream();

//模板中要插入图片的数据

byte[] img = null;

try (InputStream input = new FileInputStream(this.getClass().getClassLoader().getResource("template/timg.jpg").getPath())){

img = new byte[input.available()];

input.read(img);

} catch (Exception e) {

e.printStackTrace();

}

//要插入的map数据

Map m = new HashMap<>();

m.put("today", LocalDate.now().toString());

m.put("active", "游泳");

//处理好数据后就是超级简单的调用

return Docx4jUtil.of(path)

.addParam("title", "测试文档标题")

.addParam("user", "测试人")

.addParams(m)

.addTable("name", 2, list)

.addImg("img", img)

.get();

}

四、扩展

1.word转html

使用poi的maven

fr.opensagres.xdocreport

xdocreport

2.0.2

org.apache.poi

poi

${poi-version}

org.apache.poi

poi-scratchpad

${poi-version}

org.apache.poi

poi-ooxml

${poi-version}

org.apache.poi

poi-ooxml-schemas

${poi-version}

org.apache.poi

ooxml-schemas

1.4

org.apache.commons

commons-compress

1.18

2.工具类

package com.zb.hello.util;

import fr.opensagres.poi.xwpf.converter.xhtml.Base64EmbedImgManager;

import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;

import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;

import org.apache.commons.codec.binary.Base64;

import org.apache.poi.hwpf.HWPFDocumentCore;

import org.apache.poi.hwpf.converter.PicturesManager;

import org.apache.poi.hwpf.converter.WordToHtmlConverter;

import org.apache.poi.hwpf.converter.WordToHtmlUtils;

import org.apache.poi.xwpf.usermodel.XWPFDocument;

import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilderFactory;

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.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

public class WordHtmlUtil {

//doc转换html

public static String docToHtml(File file) throws IOException, ParserConfigurationException, TransformerException {

HWPFDocumentCore wordDocument = WordToHtmlUtils.loadDoc(new FileInputStream(file));

WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(

DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()

);

PicturesManager pictureRunMapper = (bytes, pictureType, s, v, v1) -> "data:image/png;base64,"+Base64.encodeBase64String(bytes);

wordToHtmlConverter.setPicturesManager(pictureRunMapper);

wordToHtmlConverter.processDocument(wordDocument);

Document htmlDocument = wordToHtmlConverter.getDocument();

ByteArrayOutputStream out = new ByteArrayOutputStream();

DOMSource domSource = new DOMSource(htmlDocument);

StreamResult streamResult = new StreamResult(out);

TransformerFactory transformerFactory = TransformerFactory.newInstance();

Transformer serializer = transformerFactory.newTransformer();

serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

serializer.setOutputProperty(OutputKeys.INDENT, "yes");

serializer.setOutputProperty(OutputKeys.METHOD, "html");

serializer.transform(domSource, streamResult);

out.close();

return new String(out.toByteArray());

}

//docx转换html

public static String docxToHtml(File file) throws IOException {

XWPFDocument docxDocument = new XWPFDocument(new FileInputStream(file));

XHTMLOptions options = XHTMLOptions.create();

//图片转base64

options.setImageManager(new Base64EmbedImgManager());

// 转换htm11

ByteArrayOutputStream htmlStream = new ByteArrayOutputStream();

XHTMLConverter.getInstance().convert(docxDocument, htmlStream, options);

htmlStream.close();

return new String(htmlStream.toByteArray());

}

}

java docx4j 使用教程_docx4j深入学习整理相关推荐

  1. 《Java 2 实用教程》课程学习(17)——《Java 程序设计》实验指导书-校内实验教材

    ****大学 <Java程序设计> 实验指导书 编者:王* 潘** 肖* 杨** 主审:刘** ********学院信息科学系 2013年1月9日 前  言 <Java 程序设计实验 ...

  2. 课工场java新手基础教程_Java新手学习路线,学Java不走弯路

    Java新手学习路线,学Java不走弯路 很多人都会有一个疑问,就是学习Java能看懂,但是不会写,所以学习Java一定要掌握一个有效率的学习方法,一个适合自己的学习方法,作为一个新人,千万不要自己瞎 ...

  3. 《Java 2 实用教程》课程学习(5)——第5章 子类与继承

    5.1 继承 class A { int i,j;void showIJ(){ System.out.println("I and J: "+i+" "+j); ...

  4. java 接口入门,Java接口入门教程解读

    Java接口入门教程解读,学习Java技术开发是一个长期的过程,今天小编介绍Java接口相关知识内容 接口 是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量.构造方法和成员方法 ...

  5. 前端开始学java_[Java教程]开启前端学习之路

    [Java教程]开启前端学习之路 0 2014-06-10 17:00:06 前言 第一次在博客园写博客,写写自己开启前端学习之路.应该是受邢师兄的影响吧,不得不说邢师兄人很好,学习也很认真,师兄的前 ...

  6. Java设计模式(学习整理)---命令模式

    设计模式之Command(学习整理) 1.Command定义 不少Command模式的代码都是针对图形界面的,它实际就是菜单命令,我们在一个下拉菜单选择一个命令时,然后会执行一些动作. 将这些命令封装 ...

  7. java基础学习整理(一)

    java基础学习整理(一) lesson1: D0s命令: 1.回到根目录,>cd \ 2.复制命令行下的内容,右击标记所要复制的内容,这样就已经复制好了,右击粘贴就可以了. 3.查看,设置环境 ...

  8. 学习笔记之Java程序设计实用教程

    Java程序设计实用教程 by 朱战立 & 沈伟 学习笔记之JAVA多线程(http://www.cnblogs.com/pegasus923/p/3995855.html) 国庆休假前学习了 ...

  9. 小白零基础学习Java开发入门教程奉上,希望对你有所帮助!

    "持久和新"是编程语言方面对Java的适当评估. 想要进入互联网行业,想转向编程,Java无疑是一个非常普遍的选择. 但是,Java毕竟是一种编程语言,并且仍然存在一些技术障碍.如 ...

  10. 适合Java零基础小白学习的Java零基础教程

    很多Java零基础小白,在刚刚快入门的时候玩命的学习,玩命的记住Java原理,天天早上五点起床背Java的一些英文词汇,然后遇见一些未知的困难,让自己打到癫狂状态,逐渐迷失自我放弃Java,为了解决这 ...

最新文章

  1. Paper9:Fast RCNN
  2. C3P0_and_pro.properties配置文档代码
  3. Oracle的存储过程和存储函数
  4. 终极会话劫持工具SSClone
  5. opengl三维图形绘制_Python matplotlib绘图示例 - 绘制三维图形
  6. 使用CLI设置WildFly绑定地址并关闭
  7. Java-if选择结构
  8. ERP(进纯销)系统如何开发,各类型系统都应该怎么做?
  9. python输出被五整除的数_python中给定一系列正整数能被5整除的数字中所有偶数的和?...
  10. 六石管理学:做产品,要确定自己是太子还是陪太子
  11. 记一次被动的网卡升级:VMWare导致的无线网卡不能启用
  12. 小谈一下Qt的绘制引擎(结尾有彩蛋)
  13. 独立于计算机系统的是 用户模式,2019年12月网络教育统考《计算机应用基础》复习题(十三)...
  14. illustrator插件--常用功能开发--色标生成器--js脚本开发--AI插件
  15. C语言中 指针变量 取地址符的用法 *指针变量名的用法
  16. 玩转Python脚本开发-01
  17. Android中的二维码生成与扫描
  18. EMANet:Expectation-Maximization Attention Networks for Semantic Segmentation论文解读和代码解读
  19. iPhone开发系列文章(四)-开发iPhone应用程序(一)
  20. ArcGIS Pro对TIff高程数据进行切片

热门文章

  1. java 获取身份证前两位对应省份
  2. webex java插件_Linux安装Java和Webex
  3. a链接下载文件时,会打开新页面然后下载
  4. android 一键新机,改机概述 xposed 改机缺点
  5. xampp使用教程php,php集成套件服务器xampp安装使用教程
  6. Tcp协议socket通信数据包粘包问题分析及解决方案
  7. 华硕H81M-CT主板开机报USB Device over current status Detected,15秒后关机维修一例
  8. SQL基础教程(第2版)读书笔记
  9. 去哪儿APP设计总结
  10. 宅男福利:Python爬取某站所有漫画(赶紧收藏)