Java生成 word报告

Java生成 word报告

  • 一、方案比较
  • 二、Apache POI 生成
  • 三、FreeMarker 生成

在网上找了好多天将数据库信息导出到 word 中的解决方案,现在将这几天的总结分享一下。总的来说,Java 导出 word 大致有 5 种。

一、方案比较

1. Jacob

Jacob 是 Java-COM Bridge 的缩写,它在 Java 与微软的 COM 组件之间构建一座桥梁。通过 Jacob 实现了在 Java 平台上对微软 Office 的 COM 接口进行调用。

优点:调用微软 Office 的 COM 接口,生成的 word 文件格式规范。

缺点:服务器只能是 windows 平台,不支持 unix 和 linux,且服务器上必须安装微软 Office。

2. Apache POI

Apache POI 包括一系列的 API,它们可以操作基于 MicroSoft OLE 2 Compound Document Format的各种格式文件,可以通过这些API在Java中读写Excel、Word等文件。

优点:跨平台支持 windows、unix 和 linux。

缺点:相对与 word 文件的处理来说,POI 更适合 excel 处理,对于 word 实现一些简单文件的操作凑合,不能设置样式且生成的 word 文件格式不够规范。

3. Java2word

Java2word 是一个在 Java 程序中调用 MS Office Word 文档的组件(类库)。该组件提供了一组简单的接口,以便 Java 程序调用它的服务操作 word 文档。这些服务包括:打开文档、新建文档、查找文字、替换文字、插入文字、插入图片、插入表格,在书签处插入文字、插入图片、插入表格等。

优点:足够简单,操作起来要比 FreeMarker 简单的多。

缺点:没有 FreeMarker 强大,不能根据模板生成 word 文档,word 文档的样式等信息都不能够很好的操作。

4. FreeMarker

FreeMarker 生成 word 文档的功能是由 XML + FreeMarker 来实现的。先把 word 文件另存为 xml,在 xml 文件中插入特殊字符串占位符,将 xml 翻译为 FreeMarker 模板,最后用 Java 来解析 FreeMarker 模板,编码调用 FreeMarker 实现文本替换并输出 doc。

优点:比 Java2word 功能强大,也是纯 Java 编程。

缺点:生成的文件本质上是 xml,不是真正的 word 文件格式,有很多常用的 word 格式无法处理或表现怪异,比如:超链接、换行、乱码、部分生成的文件打不开等。

5. PageOffice

PageOffice 生成 word 文件。PageOffice 封装了微软 Office 繁琐的 vba 接口,提供了简洁易用的 Java 编程对象,支持生成 word 文件,同时实现了在线编辑 word 文档和读取 word 文档内容。

优点:跨平台支持 windows、unix 和 linux,生成 word 文件格式标准,支持文本、图片、表格、字体、段落、颜色、超链接、页眉等各种格式的操作,支持多 word 合并,无需处理并发,不耗费服务器资源,运行稳定。

缺点:必须在客户端生成文件(可以不显示界面),不支持纯服务器端生成文件

二、Apache POI 生成

基本概念
XWPFDocument代表一个 docx 文档
XWPFParagraph代表文档、表格、标题等各种的段落,由多个XWPFRun组成
XWPFRun代表具有同样风格的一段文本
XWPFTable代表一个表格
XWPFTableRow代表表格的一行
XWPFTableCell代表表格的一个单元格
XWPFChar表示.docx文件中的图表
XWPFHyperlink表示超链接
XWPFPicture代表图片
XWPFComment代表批注
XWPFFooter代表页脚
XWPFHeader代表页眉
XWPFStyles样式(设置多级标题的时候用)
  1. 依赖:
<!--操作excel / docx合并-->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>4.1.2</version>
</dependency>

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>4.1.2</version>
</dependency>
  1. 正文段落

一个文档包含多个段落,一个段落包含多个 Runs,一个 Runs 包含多个 Run,Run 是文档的最小单元

获取所有段落:List paragraphs = word.getParagraphs();

获取一个段落中的所有 Runs:List xwpfRuns = xwpfParagraph.getRuns();

获取一个 Runs 中的一个 Run:XWPFRun run = xwpfRuns.get( index );

XWPFRun 代表具有相同属性的一段文字

  1. 正文表格

一个文档包含多个表格,一个表格包含多行,一行包含多列(格),每一格的内容相当于一个完整的文档

获取所有表格:List xwpfTables = doc.getTable();

获取一个表格的行数:int rcount = xwpfTable.getNumberOfRows();

获取一个表格的第几行:XWPFTableRow row = table.getRow( i );

获取一个表格中的所有行:List xwpfTableRows = xwpfTable.getRows();

获取一行中的所有列:List xwpfTableCells = xwpfTableRow.getTableCells();

获取一格里的内容:List paragraphs = xwpfTableCell.getParagraphs();

  • 表格的一格相当于一个完整的 docx 文档,只是没有页眉和页脚。里面可以有表格,使用 xwpfTableCell.getTable() 获取等等
  • 在 POI 文档中段落和表格是完全分开的,如果在两个段落中有一个表格,在 POI 中是没办法确定表格在段落中间的。只有文档的格式固定,才能正确的得到文档的结构。
  1. 页眉

一个文档可以有多个页眉,页眉里面可以包含段落和表格

获取文档的页眉:List headerList = doc.getHeaderList();

获取页眉里面的所有段落:List paras = header.getParagraphs();

获取页眉里的所有表格:List tables = header.getTables();

  1. 页脚

页脚和页眉基本类似,可以获取表示页数的角标

  1. 参考

(1) POI 创建 word 文档简单示例

XWPFDocument doc = new XWPFDocument();// 创建Word文件
XWPFParagraph p = doc.createParagraph();// 新建一个段落
p.setAlignment(ParagraphAlignment.CENTER);// 设置段落的对齐方式
p.setBorderBottom(Borders.DOUBLE);// 设置下边框
p.setBorderTop(Borders.DOUBLE);// 设置上边框
p.setBorderRight(Borders.DOUBLE);// 设置右边框
p.setBorderLeft(Borders.DOUBLE);// 设置左边框
XWPFRun r = p.createRun();// 创建段落文本
r.setText("POI创建的Word段落文本");
r.setBold(true);// 设置为粗体
r.setColor("FF0000");// 设置颜色
p = doc.createParagraph();// 新建一个段落
r = p.createRun();
r.setText("POI读写Excel功能强大、操作简单。");
XWPFTable table= doc.createTable(3, 3);// 创建一个表格
table.getRow(0).getCell(0).setText("表格1");
table.getRow(1).getCell(1).setText("表格2");
table.getRow(2).getCell(2).setText("表格3");
FileOutputStream out = new FileOutputStream("d:\\POI\\sample.doc");
doc.write(out);
out.close();

在这里插入图片描述
(2) POI 读取 word 文档里的文字

FileInputStream stream = new FileInputStream("d:\\POI\\sample.doc");
XWPFDocument doc = new XWPFDocument(stream); //创建Word文件
for(XWPFParagraph p : doc.getParagraphs()){ //遍历段落
	System.out.print(p.getParagraphText());
}
for(XWPFTable table : doc.getTables()){ //遍历表格
	for(XWPFTableRow row : table.getRows()){
		for(XWPFTableCell cell : row.getTableCells()){
			System.out.print(cell.getText());
		}
	}
}

(3) 代码示例

该代码示例只是一个 demo,简单生成了一个 word 文件,包括 word 文档常规的一些样式设置:文件字体、首行缩进、文字大小、段落对齐方式、换行。还有常见的表格创建,以及表格合并效果等。

代码:

public void createFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
    //创建文本对象
    XWPFDocument docxDocument = new XWPFDocument();

    //创建第一段落
    XWPFParagraph firstParagraphX = docxDocument.createParagraph();
    firstParagraphX.setAlignment(ParagraphAlignment.CENTER);

    XWPFRun runTitle = firstParagraphX.createRun();
    runTitle.setText("医院报告申请"); //标题
    runTitle.setBold(true); //加粗
    runTitle.setFontSize(24); //文字大小
    runTitle.setFontFamily("宋体"); //字体
    runTitle.addCarriageReturn(); //回车键
    runTitle.setKerning(30); //字间距

    XWPFParagraph paragraphX = docxDocument.createParagraph();

    paragraphX.setAlignment(ParagraphAlignment.LEFT); //对齐方式
    paragraphX.setFirstLineIndent(400); //首行缩进
    //创建段落中的run
    XWPFRun run = paragraphX.createRun();
    run.setText("开始新的额一页了健康卡离开了危,机容量为金融界王仁君我快速建房可谓集,有分页吗,按时交付问我问问");
    //run.addCarriageReturn();//回车键

    XWPFRun run2 = paragraphX.createRun();
    run2.setText("这是第二段了吧,接口了就废了我今儿来将危及,不知道嗯么回事了了,啦啦啦啦啦啦啦");
    run2.setText("这个不是能分段吗,测试一下试试");
    run2.setBold(true);//加粗

    //创建第二段落
    XWPFParagraph paragraphX2 = docxDocument.createParagraph();
    paragraphX2.setIndentationFirstLine(420); //首行缩进
    XWPFRun secondRun = paragraphX2.createRun();
    secondRun.setText("第二天的开始,就忙吧尽快立法捡垃圾而");
    secondRun.setColor("FFC0CB");
    secondRun.setUnderline(UnderlinePatterns.SINGLE);
    secondRun.addCarriageReturn();

    //创建表格 4行*5列(创建table 时,会有一个默认一行一列的表格)
    XWPFTable table = docxDocument.createTable(4,5);
    table.setWidth("95%");
    table.setWidthType(TableWidthType.PCT); //设置表格相对宽度
    table.setTableAlignment(TableRowAlign.CENTER); //居中对齐

    //合并单元格
    XWPFTableRow row1 = table.getRow(0); //第一行
    XWPFTableCell cell1 = row1.getCell(0); //第一行的第一列
    CTTcPr cellCtPr = getCellCTTcPr(cell1);
    cellCtPr.addNewHMerge().setVal(STMerge.RESTART);

    XWPFTableCell cell2 = row1.getCell(1); //第一行的第二列
    CTTcPr cellCtPr2 = getCellCTTcPr(cell2);
    cellCtPr2.addNewHMerge().setVal(STMerge.CONTINUE);

    //给表格填充文本
    setTableText(docxDocument);


    XWPFParagraph endParagraphX = docxDocument.createParagraph();
    endParagraphX.setAlignment(ParagraphAlignment.RIGHT);

    XWPFRun endRun = endParagraphX.createRun();
    endRun.setText("2021年11月18日");

    String path="D://POI//docBoke.docx";
    File file = new File(path);
    FileOutputStream stream = new FileOutputStream(file);
    docxDocument.write(stream);
    stream.close();
    System.out.println("文件生成完成!");
}

private void setTableText(XWPFDocument docxDocument) {
    //获取第一个表格
    XWPFTable table = docxDocument.getTableArray(0);
    List<XWPFTableRow> rows = table.getRows();
    int i=1;
    for(XWPFTableRow row :rows){
        List<XWPFTableCell> cells = row.getTableCells();
        for(XWPFTableCell cell: cells){
            cell.setText("第"+String.valueOf(i++)+"格");
            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); //中心垂直对齐
            //cell.setWidthType(TableWidthType.PCT);
            //cell.setWidth("30%");
        }
    }
}

public static CTTcPr getCellCTTcPr(XWPFTableCell cell) {
    CTTc cttc = cell.getCTTc();
    CTTcPr tcPr = cttc.isSetTcPr() ? cttc.getTcPr() : cttc.addNewTcPr();
    return tcPr;
}

运行之后,就会在指定目录下生成名为 “ docBoke.docx ” 的 word 报告文件
在这里插入图片描述

三、FreeMarker 生成

FreeMarker 是一个基于 Java 的模板引擎,最初专注于使用 MVC 软件架构生成动态网页。但是,它是一个通用的模板引擎,不依赖于 servlets 或 HTTP 或 HTML,因此它通常还用于生成源代码,配置文件或电子邮件。
此时,我们用它动态生成的 xml 文件,进而导出 word 文档。

  1. 流程图
    在这里插入图片描述
  2. 模板制作
    先用 word 做一个模板,如下图:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/8a6c7451cc074715b463f764f7006c00.png

(注意,上面是有表格的,我设置了边框不可见)然后另存为 xml 文件,之后用工具打开这个 xml 文件,有人用 firstobject xml editor 感觉还不如 notePad++ ,我这里用 notePad++,主要是有高亮显示,和元素自动配对,效果如下:
在这里插入图片描述
上面黑色的地方基本是我们之后要替换的地方,比如xytitle替换为${xytitle},对于表格要十分注意,比如选择题下面的表格,我们可以通过<w:tr>查找来定位,一对<w:tr></w:tr>代表一行,也就是一条记录(一道题),我们这里要用一对<#list></#list>来降其包括,以便后续填充数据,具体可以参照FreeMarker页面语法。
例如这里选择题,我们是两行为一条记录,所以要<#list></#list>包括两行,形如:
<#list table as plan1><w:tr>题号 题目</w:tr><w:tr>选项</w:tr></#list>
然后在这其中找到对应的xzn,xztest,ans1,ans2,ans3,ans4替换为${plan1.xzn},${plan1.xztest},${plan1.ans1},${plan1.ans2},${plan1.ans3},${plan1.ans4},注意这里的table1plan1命名,table1后续填充数据要用到,其他的替换同理操作,
将 xml 文件格式化:在线格式化
在这里插入图片描述

在这里插入图片描述
全部参数预设完成后保存,修改后缀名为ftl,至此模板制作完毕。

  1. 代码实现

依赖:

<!-- freemarker 用于动态写入word文档 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.9</version>
</dependency>

代码:

public class DocumentHandler {

    private Configuration configuration = null;
    

    public DocumentHandler() {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
    }

	/*
     * 转换成word
     */
    public void createDoc(Map<String,Object> dataMap, String fileName) throws UnsupportedEncodingException {
        //dataMap 要填入模本的数据文件
        //设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
        //这里我们的模板是放在template包下面
        configuration.setClassForTemplateLoading(this.getClass(), "/templates");
        Template t=null;
        try {
            //.ftl文件为要装载的模板
            t = configuration.getTemplate("document.ftl");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //输出文档路径及名称
        File outFile = new File(fileName);
        Writer out = null;
        FileOutputStream fos=null;
        try {
            fos = new FileOutputStream(outFile);
            OutputStreamWriter oWriter = new OutputStreamWriter(fos,"UTF-8");
            //这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
            //out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
            out = new BufferedWriter(oWriter);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }

        try {
            //将数据填入模板文件,并输出到目标地址
            t.process(dataMap, out);
            out.close();
            fos.close();
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //System.out.println("---------------------------");
    }
}
public static void main(String[] args) throws UnsupportedEncodingException {

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("xytitle", "试卷");
        int index = 1;
        // 选择题
        List<Map<String, Object>> list1 = new ArrayList<Map<String, Object>>();//题目
        List<Map<String, Object>> list11 = new ArrayList<Map<String, Object>>();//答案
        index = 1;
        for (int i = 0; i < 3; i++) {

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("xzn", index + ".");
            map.put("xztest",
                    "(   )操作系统允许在一台主机上同时连接多台终端,多个用户可以通过各自的终端同时交互地使用计算机。");
            map.put("ans1", "A" + index);
            map.put("ans2", "B" + index);
            map.put("ans3", "C" + index);
            map.put("ans4", "D" + index);
            list1.add(map);

            Map<String, Object> map1 = new HashMap<String, Object>();
            map1.put("fuck", index + ".");
            map1.put("abc", "A" + index);
            list11.add(map1);

            index++;
        }
        dataMap.put("table1", list1);
        dataMap.put("table11", list11);

        // 填空题
        List<Map<String, Object>> list2 = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> list12 = new ArrayList<Map<String, Object>>();
        index = 1;
        for (int i = 0; i < 2; i++) {

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("tkn", index + ".");
            map.put("tktest",
                    "操作系统是计算机系统中的一个___系统软件_______,它管理和控制计算机系统中的___资源_________.");
            list2.add(map);

            Map<String, Object> map1 = new HashMap<String, Object>();
            map1.put("fill", index + ".");
            map1.put("def", "中级调度" + index);
            list12.add(map1);

            index++;
        }
        dataMap.put("table2", list2);
        dataMap.put("table12", list12);

        // 判断题
        List<Map<String, Object>> list3 = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> list13 = new ArrayList<Map<String, Object>>();
        index = 1;
        for (int i = 0; i < 3; i++) {

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("pdn", index + ".");
            map.put("pdtest",
                    "复合型防火墙防火墙是内部网与外部网的隔离点,起着监视和隔绝应用层通信流的作用,同时也常结合过滤器的功能。");
            list3.add(map);

            Map<String, Object> map1 = new HashMap<String, Object>();
            map1.put("judge", index + ".");
            map1.put("hij", "对" + index);
            list13.add(map1);

            index++;
        }
        dataMap.put("table3", list3);
        dataMap.put("table13", list13);

        // 简答题
        List<Map<String, Object>> list4 = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> list14 = new ArrayList<Map<String, Object>>();
        index = 1;
        for (int i = 0; i < 2; i++) {

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("jdn", index + ".");
            map.put("jdtest", "说明作业调度,中级调度和进程调度的区别,并分析下述问题应由哪一级调度程序负责。");
            list4.add(map);

            Map<String, Object> map1 = new HashMap<String, Object>();
            map1.put("answer", index + ".");
            map1.put("xyz", "说明作业调度,中级调度和进程调度的区别,并分析下述问题应由哪一级调度程序负责。");
            list14.add(map1);

            index++;
        }
        dataMap.put("table4", list4);
        dataMap.put("table14", list14);

        DocumentHandler mdoc = new DocumentHandler();
        mdoc.createDoc(dataMap, "E:/excel/考题.docx");

    }
  • 注意上面 map 中的 key 必须和模板中的相对应,否则会报错。导出效果如下:
    在这里插入图片描述

好事定律:每件事最后都会是好事,如果不是好事,说明还没到最后。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/431830.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

7款炫酷的前端动画特效分享(三)(附效果图及在线演示)

分享7款好玩的前端动画特效 其中有CSS动画、SVG动画、js小游戏等等 下方效果图可能不是特别的生动 那么你可以点击在线预览进行查看相应的动画特效 同时也是可以下载该资源的 CSS3模仿四季交替动画 基于HTML5CSS3实现的卡通风格一年四季交替动画特效 以下效果图只能体现框架的…

ThreadPoolExecutor 学习

ThreadPoolExecutor 是开发中最常用的线程池&#xff0c;今天来简单学习一下它的用法以及内部构造。 1、线程池存在的意义&#xff1f; 一般在jvm上&#xff0c;用户线程和操作系统内核线程是1&#xff1a;1的关系&#xff0c;也就是说&#xff0c;每次创建、销毁线程的时候&am…

10.WEB渗透测试-Linux基础知识-Linux用户权限管理(下)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;9.WEB渗透测试-Linux基础知识-Linux用户权限管理&#xff08;上&#xff09;-CSDN博客 ch…

Linux进程详细介绍

文章目录 Linux进程1、计算机体系结构和操作系统管理1.1、计算机体系结构 -- 硬件1.2、操作系统&#xff08;Operator System&#xff09; -- 软件 2、进程2.1、进程基本概念2.2、进程标识符2.2.1、获取当前进程标识符和当前进程的父进程标识符2.2.2、通过系统调用创建进程 -- …

微信小程序开发学习笔记《19》uni-app框架-配置小程序分包与轮播图跳转

微信小程序开发学习笔记《19》uni-app框架-配置小程序分包与轮播图跳转 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。建议仔细阅读uni-app对应官方文档 一、配置小程序分包 分包可以减少小程序首次启动时的加载时间 为此&#…

Google Play上架:自查封号政策解析(高风险行为之不允许破坏Google Play生态系统中用户信任度的应用或应用内容)

本文章提供给近期被封号的开发者们&#xff0c;希望能带来帮助&#xff0c;有其他的自查方向后续也会发布出来。 ——————————————————————————————————————— 用户数据设备和网络滥用 用户数据 设备和网络滥用

前端学习之HTML(第二天)--多媒体标签和表格标签

注&#xff1a;里面的注释是对各个标签的解释 多媒体标签 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title></title> </head> <body> <!-- audio是音频可以填写绝对路径也可填写相对路径 --> &l…

解决微软活动目录管理工作中常见问题

微软活动目录&#xff08;AD域&#xff09;是一种由微软的用于管理网络中用户、计算机、资源等的目录服务。活动目录被广泛应用于企业内部的网络管理中&#xff0c;尤其是对于使用微软产品的企业来说&#xff0c;活动目录是至关重要的基础设施之一。 因此&#xff0c;以微软为…

索引下推 INDEX CONDITION PUSHDOWN

索引下推 (INDEX CONDITION PUSHDOWN&#xff0c;简称ICP)是在 MySQL5.6 针对扫描索引下推二级索引的一项优化改进。 用来在范围查询时减少回表的次数。ICP适用于 MYISAM和INNODB.

ref和reactive用哪个?

ref和reactive用哪个? 1.&#x1f916;GPT&#x1f916;:ref和reactive用哪个根据数据类型而定 ref 用于将基本类型的数据&#xff08;如字符串、数字&#xff0c;布尔值等&#xff09;转换为响应式数据。使用 ref 定义的数据可以通过 .value 属性访问和修改。 reactive 用于…

JavaScript 学习笔记(7)

一模板字符串 1.用途 允许在字符串中嵌入表达式和变量&#xff0c;是一种方便的字符串语法 2.用法 模板字符串使用反引号 作为字符串的定界符分隔的字面量&#xff1b;模板字面量是用反引号&#xff08;&#xff09;分隔的字面量&#xff0c;允许多行字符串、带嵌入表达式…

ElasticSearch之分布式查询过程分析

写在前面 本文一起看下es分布式查询的过程。 1&#xff1a;分布式搜索过程 分布式搜索分为两个阶段&#xff0c;query和fetch,即query-then-fetch。 假定primary shard3,replica shard1&#xff0c;即3个主分片&#xff0c;1个副本分片。 1.1&#xff1a;query阶段 某data …

二叉树——700. 二叉搜索树中的搜索、98. 验证二叉搜索树

二叉搜索树中的搜索 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 示例 1: 输入&#xff1a;root [4,2,7,1,3], val 2 …

【论文精读】基于知识图谱关系路径的多跳智能问答模型研究

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

96道前端面试题,前端开发工作内容

HTML、CSS、JS三大部分都起什么作用&#xff1f; HTML内容层&#xff0c;它的作用是表示一个HTML标签在页面里是个什么角色&#xff1b;CSS样式层&#xff0c;它的作用是表示一块内容以什么样的样式&#xff08;字体、大小、颜色、宽高等&#xff09;显示&#xff1b;JS行为层…

js形参传递特殊字符

在前端我们给其他页面传值或者传数据到后台的时候&#xff0c;字符串经常将一些特殊符号识别成字符集。这种情况下会将数据打断或者打乱&#xff0c;比如字符串里面包含*/&这些符号的时候就会错误。 我们可以通过将字符中的特殊字符替换成十六进制的字符&#xff0c;一些特…

【详识JAVA语言】String类2

常用方法 字符串的不可变性 String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改&#xff0c;是因为&#xff1a; 1. String类在设计时就是不可改变的&#xff0c;String类实现描述中已经说明了 以下来自JDK1.8中String类的部分实现&#xff1a; String类…

马士超:符合国际标准的沉浸式音频HOLOSOUND的发展与未来 | 演讲嘉宾公布

一、3D音频 3D 音频分论坛将于3月27日同期举办&#xff01; 3D音频技术不仅能够提供更加真实、沉浸的虚拟世界体验&#xff0c;跨越时空的限制&#xff0c;探索未知的世界。同时&#xff0c;提供更加丰富、立体的情感表达和交流方式&#xff0c;让人类能够更加深入地理解彼此&a…

【Python 识别某滑块的距离】今天来换思维搞滑块,不用识别库,几行代码就能搞定,仅供学习

写作日期&#xff1a;2024.03.05 使用工具&#xff1a;Python 温馨提示&#xff1a;此方法仅对有完整图和缺口图的滑块有效&#xff0c;可精准识别出缺口要滑动的距离 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES处理&#xff08;直接…

2024-3-5 python 序列小知识点

1、for循环的变量作用域不限于for循环内 >>>i 10 >>>for i in range(100): >>> print(i) >>> i 100此处&#xff0c;for循环里的 i 修改了之前的 i 变量的值。 2、列表推导式里的变量作用域仅限于推导式内 推导式犹如一个函数&…