当前位置: 首页 > article >正文

java使用Apache POI 操作word文档

项目背景:

当我们对一些word文档(该文档包含很多的标题比如 1.1 ,1.2 , 1.2.1.1, 1.2.2.3)当我们删除其中一项或者几项时,需要手动的对后续的进行补充。该功能主要是对标题进行自动的补充。

具体步骤:

导入依赖:

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency>

官网网址:(觉得麻烦不可也许)

Apache Poi 官方链接 可以看官方文档,其实更方便的可以直接导入依赖后,下载源代码,直接看源码的注释也许

跑一下代码熟悉一下

首先把下面的代码复制到编译器跑一下,看看是否正常运行,顺便了解基本使用

package codeByZyc;import org.apache.poi.xwpf.usermodel.*;import java.io.FileInputStream;
import java.io.IOException;public class rederWordTest {public static void main(String[] args) throws IOException {FileInputStream file = new FileInputStream("输入你的word文档地址");XWPFDocument document = new XWPFDocument(file);// 获取word中的段落,无法获取表格System.out.println("获取到的段落");for (XWPFParagraph paragraph : document.getParagraphs()) {System.out.println(paragraph.getText());}//  这是只能获取word中的表格System.out.println("获取到的表给内容");for (XWPFTable table : document.getTables()) {for (XWPFTableRow row : table.getRows()) {for (XWPFTableCell cell : row.getTableCells()) {System.out.print(cell.getText() + " \t");}System.out.println();}}document.close();file.close();}}

api说明

通过上面的代码,我们可以知道poi是用过XWPFDocument这个类去获取的word内容。 下面从段落和表格两部分进行代码说明

段落api说明

对于word中的段落他的操作如下:

XWPFDocument(最大的模块).getParagraphs->Paragraph(负责每一个段落).getRuns->Run(这是最小处理的元素)

下面是进行调式的图片,配合图片更好理解:

XWPFDocument:就是最大的那个模块 信息很大

在这里插入图片描述

Paragraphs:这是所有的段落集合

在这里插入图片描述

Paragraph:存放的就是每一段了 里面的runs 是按照格式进行分割的

在这里插入图片描述

Runs run的集合

具体看下面

Run(最基础的元素)

这是最重要的那个元素,他是构成所有段落和表格的最小单位。
一个段落他是如何划分成几个run的?
他是按照每个字的前后 是否同一个格式(字体,加粗否,大小等)必须完全一样才能分到一个run里面。具体分割还得调式看

下图是一些run的切割:
在这里插入图片描述
这个就是特殊的符号会被划开
在这里插入图片描述
这个更离谱 注意 1.3.1后面的空格没有 ,这个的空格是被划开的。是因为空格的格式和标题不一样
在这里插入图片描述

段落代码(直接看结尾的整合代码,写得更详细注释更全面):里面有注释 应该算比较清楚了 有问题可以下面评论

文件路径自己填写一下

package codeByZyc;import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class word {// 匹配数字开头,小数点隔开 空格后接内容static Pattern headerPattern = Pattern.compile("^(\\d+(?:\\.\\d+)*)(\\s+.*)");//用于计算层级static ArrayList<Integer> headerlist= new ArrayList();//用于存放段落开头有单个特殊符号的static ArrayList<String> kaitou =new ArrayList<>();// 匹配中文括号列表项(如 (1))
//   static Pattern listItemPattern = Pattern.compile("^((\\d+))(.*)$");public static void main(String[] args) {String path="文件路径";//初始化计算器for (int i = 0; i < 10; i++) {headerlist.add(0);}//初始化开头特殊字符kaitou.add("★");kaitou.add("*");//执行代码updateWord(path);}public static void updateWord(String path){try {// 1. 读取 .docx 文件FileInputStream fis = new FileInputStream(path);XWPFDocument document = new XWPFDocument(fis);//获取word每一个段落元素(不包含表格的)List<XWPFParagraph> paragraphs = document.getParagraphs();//  //一个段落一个段落的处理for (int i = 0; i < paragraphs.size(); i++) {wordDuanluo(paragraphs.get(i));}//开始村存回去FileOutputStream out = new FileOutputStream("文件路径代码生成.docx");document.write(out);// 4. 关闭流document.close();fis.close();out.close();} catch (Exception e) {e.printStackTrace();}}//处理段落private static void wordDuanluo(XWPFParagraph paragraph) {//每个段落下面还有更小的元素,叫run 所以处理runList<XWPFRun> runs = paragraph.getRuns();//直接匹配第一个 是那就是标题 不是那就是正文if (runs.size()==1){wordRun(runs.get(0));}else if (runs.size()==2){//只有两个识别开头是不是包含特殊  时走一个通道 不是走二通道//标志是否匹配boolean flagkaitou= false;for (int i = 0; i < kaitou.size(); i++) {if (kaitou.get(i).equals(runs.get(0).text())){flagkaitou=true;break;}}if (flagkaitou==true){//证明开头匹配走一同到wordRun(runs.get(1));}else {//不匹配wordRun(runs.get(0),runs.get(1));}}else if (runs.size()>2){//数量在三个及以上//标志是否匹配boolean flagkaitou= false;for (int i = 0; i < kaitou.size(); i++) {if (kaitou.get(i).equals(runs.get(0).text())){flagkaitou=true;break;}}if (flagkaitou==true){//证明开头匹配wordRun(runs.get(1),runs.get(2));}else {//不匹配wordRun(runs.get(0),runs.get(1));}}}// 处理非常特殊的 标题后面跟的空格字体和标题不一样分开了 进行拼接private static void wordRun(XWPFRun run1, XWPFRun run2) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run1.text()+run2.text());if (matcher.find()) {//匹配成功//保存序号后面的文章用于拼接String contex = matcher.group(2);//按照.进行切割String[] originalParts = matcher.group(1).split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);//序号放到run1  空格+正文放到run2run1.setText(result.toString(),0);run2.setText(contex,0);}}private static void wordRun(XWPFRun run) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run.text());if (matcher.find()) {//匹配成功//保存序号后面的文章用于拼接String contex = matcher.group(2);//按照.进行切割String[] originalParts = matcher.group(1).split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);result.append(contex);//将内容替换到runrun.setText(result.toString(),0);}}}
表格api说明 基本上和段落一样 有一点点不一样
XWPFDocument(最大的模块).getTables->XWPFTable(负责每一个表格).getRows->Row(代表一行).getTableCells->XWPFTableCell(每一格子)[由于cell无法更改具体看下图] 需要深入到 run

注意,我原来以为在cell就可以更改他的文本
在这里插入图片描述
但是看源码可以知道 他是在尾部追加并不是覆盖,所以还是只能追到run去覆盖。

表格代码:(直接看结尾的整合代码,写得更详细注释更全面)
import org.apache.poi.xwpf.usermodel.*;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class TestWord {// 匹配表格的 结尾开头是数字 空格几个都行static  Pattern tablePattern = Pattern.compile("^(\\d+)(\\s*)$");static  Integer tableCount=0;//用于存放段落开头有单个特殊符号的static ArrayList<String> kaitou =new ArrayList<>();public static void main(String[] args) {String path="测试table.docx";//初始化开头特殊字符kaitou.add("★");kaitou.add("*");readWord(path);}public static void readWord(String filePath){try {// 1. 读取 .docx 文件FileInputStream fis = new FileInputStream(filePath);XWPFDocument document = new XWPFDocument(fis);//直接一层一层找一下找到 run  试过在cell进行修改 但是cell的修改是 原来的基础上进行了新的增加 不能进行替换 直接找到run进行替换for (XWPFTable table : document.getTables()) {//一个table 清除一次计数器tableCount=0;for (XWPFTableRow row : table.getRows()) {for (XWPFTableCell cell : row.getTableCells()) {for (XWPFParagraph paragraph : cell.getParagraphs()) {List<XWPFRun> runs = paragraph.getRuns();//直接匹配第一行if (runs.size()==1){tableup(runs.get(0));}else if (runs.size()>1){//这边就是 考虑到前面有个特殊符号的情况 就需要判断了XWPFRun run1 = runs.get(0);//第一个不是特殊那就直接走第一通道boolean flag=false;for (int i = 0; i < kaitou.size(); i++) {if (kaitou.get(i).equals(run1.text())){flag=true;break;}}if (flag){tableup(runs.get(1));}else {tableup(run1);}}}}}}System.out.println("测试完成");FileOutputStream out = new FileOutputStream("生成的table.docx");document.write(out);// 4. 关闭流document.close();fis.close();out.close();} catch (Exception e) {e.printStackTrace();}}public  static void  tableup(XWPFRun run){Matcher matcher = tablePattern.matcher(run.text());if (matcher.find()){//匹配成功  开始更换层级String content = matcher.group(2);String originalParts = matcher.group(1);//开始覆盖掉序号 并拼接后面的内容tableCount++;StringBuffer result=new StringBuffer();result.append(tableCount+content);//写入run.setText(result.toString(),0);}}
}

总结

整合代码:

package codeByZyc;import org.apache.poi.xwpf.usermodel.*;import java.io.FileInputStream;import java.io.FileOutputStream;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;public class Upword {// 匹配数字开头,小数点隔开 空格后接内容static Pattern headerPattern = Pattern.compile("^(\\D?)(\\d+(?:\\.\\d+)*)(\\s+)");//用于段落计算层级static ArrayList<Integer> headerlist= new ArrayList();//用于存放段落开头有单个特殊符号的// 匹配表格的 结尾开头是数字 空格几个都行static  Pattern tablePattern = Pattern.compile("^(\\D?)(\\d+)(\\s*)$");//匹配表格的层级static  Integer tableCount=0;// 匹配中文括号列表项(如 (1))
//   static Pattern listItemPattern = Pattern.compile("^((\\d+))(.*)$");public static void main(String[] args) {String path="测试专用删除部分标题.docx";//初始化段落层级计算器for (int i = 0; i < 10; i++) {headerlist.add(0);}//执行代码updateWord(path);}public static void updateWord(String path){try {// 1. 读取 .docx 文件FileInputStream fis = new FileInputStream(path);XWPFDocument document = new XWPFDocument(fis);//获取word每一个段落元素(不包含表格的)List<XWPFParagraph> paragraphs = document.getParagraphs();//  //一个段落一个段落的处理for (int i = 0; i < paragraphs.size(); i++) {wordDuanluo(paragraphs.get(i));}//获取word的表格
//            直接一层一层找一下找到 run  试过在cell进行修改 但是cell的修改是 原来的基础上进行了新的增加 不能进行替换 直接找到run进行替换for (XWPFTable table : document.getTables()) {wordtable(table);}//开始村存回去FileOutputStream out = new FileOutputStream("代码生成.docx");document.write(out);// 4. 关闭流document.close();fis.close();out.close();} catch (Exception e) {e.printStackTrace();}}//处理表格private static void wordtable(XWPFTable table){//一个table 清除一次计数器tableCount=0;for (XWPFTableRow row : table.getRows()) {for (XWPFTableCell cell : row.getTableCells()) {for (XWPFParagraph paragraph : cell.getParagraphs()) {List<XWPFRun> runs = paragraph.getRuns();//直接匹配第一行if (runs.size()==1){wordTableRun(runs.get(0));}else if (runs.size()==2){wordTableRun(runs.get(0),runs.get(1));}}}}}//处理段落private static void wordDuanluo(XWPFParagraph paragraph) {//每个段落下面还有更小的元素,叫run 所以处理runList<XWPFRun> runs = paragraph.getRuns();/* 这里需要注意一下因为我的测试文档的需求标题是这样的 *1.2.1 背景展望   像这个 要是格式不一样会被划分成 三个部分  *    1.2.1   还有一个空格  。 但是要是格式一样 就直接化成一个了主要是我的测试文档是有些一样 有些不一样所以需要考虑的比较多。*/if (runs.size()==1){//针对只划分一个的  那没得说 直接走第一个wordRun(runs.get(0));}else if (runs.size()==2){//这就是两个 那可能是两种情况:  *1.2.1  空格   或者 *   1.2.1空格   就是两种了wordRun(runs.get(0),runs.get(1));}else if (runs.size()>2){//数量在三个及以上//这种 就是我上面说的 三个格式都不一样wordRun(runs.get(0),runs.get(1),runs.get(2));}}private static void wordRun(XWPFRun run) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run.text());if (matcher.find()) {//匹配成功String  oldxuaho=matcher.group(2);//按照.进行切割String[] originalParts =oldxuaho.split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//拼接正确的序号//把序号前面的放进来result.append(matcher.group(1));for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);//替换if(run.text().contains(oldxuaho)){//进行替换String s = run.text();s.replace(oldxuaho,result.toString());run.setText(s,0);}}}// 处理非常特殊的 标题后面跟的空格字体和标题不一样分开了 进行拼接private static void wordRun(XWPFRun run1, XWPFRun run2) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run1.text()+run2.text());if (matcher.find()) {//匹配成功String  oldxuaho=matcher.group(2);//按照.进行切割String[] originalParts =oldxuaho.split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//把前面的放进来result.append(matcher.group(1));//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);//查找替换 具体思路看一看下面的if(run1.text().contains(oldxuaho)){//进行替换String s = run1.text();s.replace(oldxuaho,result.toString());run1.setText(s,0);}else if (run2.text().contains(oldxuaho)){String s = run2.text();s.replace(oldxuaho,result.toString());run2.setText(s,0);}}}private static void wordRun(XWPFRun run1, XWPFRun run2,XWPFRun run3) {//run是作为操作word的非常小的元素了,他会把每个段落换分成几个run组成  具体划分规则我也不知道 (我看案列 是按格式进行 格式一样的情况大概率是在一起)//采用正则表达式进行匹配Matcher matcher = headerPattern.matcher(run1.text()+run2.text()+run3.text());if (matcher.find()) {//匹配成功String oldxuaho=matcher.group(2);//按照.进行切割String[] originalParts = oldxuaho.split("\\.");//根据长度判断层级 一个就一级int length = originalParts.length;//文档按照顺序1  1.1  1.1.1//将子层级覆盖掉for (int i = length; i < headerlist.size(); i++) {headerlist.set(i,0);}headerlist.set(length - 1, (headerlist.get(length - 1) + 1));StringBuffer result = new StringBuffer();//直接将他们拼起来result.append(matcher.group(1));//拼接正确的序号for (int i = 0; i < length; i++) {result.append(headerlist.get(i));result.append(".");}//多出一个. 进行删除result.deleteCharAt(result.length()-1);/*下面就需要考虑 run1 2 3 如何划分了因为我的matcher.group 把他们三个合并的 拆分成了 三部分  (数字标题前面的部分) (数字标题) 空格内容(内容可能有可能无)* 情况1:  最开始说到的  *       1.2.1    空格内容(内容可能有可能无)* 情况2:  也有可能是: *1.2.1   空格内容(内容可能有可能无)     内容情况3:  也有可能是: *      1.2.1空格内容(内容可能有可能无)   内容情况4:  *1.2.1空格内容(内容可能有可能无)  内容  内容解决思路: group(2)匹配的序号 只需要 挨个便利 看看 哪个run包含 进行替换就行其他的保持不变。* *///查找if(run1.text().contains(oldxuaho)){//进行替换String s = run1.text();s.replace(oldxuaho,result.toString());run1.setText(s,0);}else if (run2.text().contains(oldxuaho)){String s = run2.text();s.replace(oldxuaho,result.toString());run2.setText(s,0);}else {String s = run3.text();s.replace(oldxuaho,result.toString());run3.setText(s,0);}}}//处理表格的单元格private static void wordTableRun(XWPFRun run){Matcher matcher = tablePattern.matcher(run.text());if (matcher.find()){//匹配成功  开始更换层级String oldxuhao  = matcher.group(2);//开始覆盖掉序号 并拼接后面的内容tableCount++;String s = run.text();s.replace(oldxuhao,tableCount.toString());//写入run.setText(s,0);}}private static void wordTableRun(XWPFRun run1,XWPFRun run2){Matcher matcher = tablePattern.matcher(run1.text()+run2.text());if (matcher.find()){String oldxuhao=matcher.group(2);//开始覆盖掉序号 并拼接后面的内容tableCount++;String s;if (run1.text().contains(oldxuhao)){s=run1.text();s.replace(oldxuhao,tableCount.toString());run1.setText(s,0);}else if (run2.text().contains(oldxuhao)){s=run2.text();s.replace(oldxuhao,tableCount.toString());run2.setText(s,0);}}}}

难点:

我感觉最大的难点就是对Api的熟悉,需要看看源码或者文档。以及利用正则表达式对标题进行匹配

相关文章:

java使用Apache POI 操作word文档

项目背景&#xff1a; 当我们对一些word文档&#xff08;该文档包含很多的标题比如 1.1 &#xff0c;1.2 &#xff0c; 1.2.1.1&#xff0c; 1.2.2.3&#xff09;当我们删除其中一项或者几项时&#xff0c;需要手动的对后续的进行补充。该功能主要是对标题进行自动的补充。 具…...

【 C/C++ 包管理工具】vcpkg安装+使用

【 C/C 包管理工具】vcpkg安装使用 Vcpkg 是由 Microsoft 和 C 社区维护的免费开源 C/C 包管理器&#xff0c;可在 Windows、macOS 和 Linux 上运行。 可以很方便的安装管理 C/C 库。 1. 安装 不要安装到Program Files这种有空格的路径下&#xff0c;否则后面安装库可能出现…...

免费开源的NAS解决方案:TrueNAS

TrueNAS是业内知名的FreeNAS系统的升级版&#xff0c;是一款开源的网络存储系统&#xff0c;具有高性能、稳定性和易用性等优点。 TrueNAS目前有三个版本&#xff0c;分别是TrueNAS CORE、TrueNAS ENTERPRISE、TrueNAS SCALE。其中&#xff0c;TrueNAS CORE基于FreeBSD开发&…...

LeetCode热题100精讲——Top1:两数之和【哈希】

你好&#xff0c;我是安然无虞。 文章目录 题目背景两数之和C解法Python解法 题目背景 如果大家对于 哈希 类型的概念并不熟悉, 可以先看我之前为此专门写的算法详解: 蓝桥杯算法竞赛系列第九章巧解哈希题&#xff0c;用这3种数据类型足矣 两数之和 题目链接&#xff1a;两数…...

github上传操作简单说明

前期准备 0.下载git&#xff08;如果已经有了就不用了&#xff09; 1.在GitHub上新建一个存储库 2.先在本地创建一个目录作为本地库目录&#xff0c;在目录里打开git bash进行上传 上传过程 echo "# Garbled_repair" >> README.md 作用&#xff1a;创建一个…...

GitLens with `Commit Graph`

文章目录 GitLens with Commit Graph GitLens with Commit Graph 想要更直观地查看 Git 提交历史&#xff1f;我打包了一个支持 Commit Graph 的 GitLens 版本&#xff0c;让你轻松在 VSCode 中查看分支、合并、变更记录等内容&#xff0c;一目了然&#xff01; &#x1f4cc…...

Rocky9.5基于sealos快速部署k8s集群

首先需要下载 Sealos 命令行工具&#xff0c;sealos 是一个简单的 Golang 二进制文件&#xff0c;可以安装在大多数 Linux 操作系统中。 以下是一些基本的安装要求&#xff1a; 每个集群节点应该有不同的主机名。主机名不要带下划线。 所有节点的时间需要同步。 需要在 K8s …...

阿里云服务器环境部署 四 MySQL主从配置

安装MySQL 导入mysql镜像 docker load -i /opt/dockerinstall/mysql/mysql-8.1.0.tar docker run --privilegedtrue --name mysql8 --restartunless-stopped -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 -v /usr/local/mysql/logs:/var/log/mysql -v /usr/local/mysql/d…...

GPT-5 将免费向所有用户开放?

GPT-5 将免费向所有用户开放&#xff1f; 硅谷知名分析师 Ben Thompson 最近与 OpenAI CEO Sam Altman 进行了一场深度对谈&#xff0c;其中Sam Altman透漏GPT-5将免费向大家发放。 OpenAI 这波操作可不是一时冲动&#xff0c;而是被逼出来的。DeepSeek 这个新秀横空出世&am…...

web客户端存储,IndexDB相关讲解

IndexDB详细讲解 IndexedDB 是浏览器提供的一种底层 API,用于在客户端存储大量结构化数据。相比 Web Storage(localStorage/sessionStorage),它支持更复杂的数据结构、事务处理、索引查询等高级功能。以下是一个系统化的讲解: 一、核心概念 1、​数据库(Database)​ 每…...

excel文件有两列,循环读取文件两列赋值到字典列表。字典的有两个key,分别为question和answer。将最终结果输出到json文件

import pandas as pd import json# 1. 读取 Excel 文件&#xff08;假设列名为 question 和 answer&#xff09; try:df pd.read_excel("input.xlsx", usecols["question", "answer"]) # 明确指定列 except Exception as e:print(f"读取文…...

项目日记 -云备份 -服务器配置信息模块

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【项目日记-云备份】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 代码已上传 gitee 目录 前言配置信息文件文件配置类getInstance 获得实例readConfigFile 读取配置信息文件 测试 #mermaid-svg-ewlCpjdOf0q0VTLI {font-family:…...

gralloc usage flags

下面这些示例主要说明了 gralloc usage flags 在图像处理和多媒体应用中如何影响性能和正确性。让我们逐个详细分析每个问题的 根因 和 修复方案&#xff0c;并深入解析 gralloc 标志对 缓存管理 和 数据流 的影响。 ✅ Example 1: 长曝光快照耗时异常 &#x1f4cc; 问题描述…...

Mysql配套测试之查询篇

&#x1f3dd;️专栏&#xff1a;Mysql_猫咪-9527的博客-CSDN博客 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 条件查询简单测试&#xff1a; 1.查询英语成绩不及格的同学(<60) 2…...

mysql——第二课

学生表 CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT,name varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,sex varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,age int(11) DEFAULT NULL,c_id int(10) DEFAULT NULL,PRIMARY KEY (id),KEY c_id (c_id),CONSTR…...

Python网络编程入门

一.Socket 简称套接字&#xff0c;是进程之间通信的一个工具&#xff0c;好比现实生活中的插座&#xff0c;所有的家用电器要想工作都是基于插座进行&#xff0c;进程之间要想进行网络通信需要Socket&#xff0c;Socket好比数据的搬运工~ 2个进程之间通过Socket进行相互通讯&a…...

arm linux下的读写信号量rw_semphore的实现

本文基于arm linux 5.10来介绍内核中使用的读写信号量rw remphore的实现代码。 内核中信号量结构体struct rw_semaphore的定义在include/linux/rwsem.h 32位architectures下&#xff0c;结构体struct rw_semaphore中的count的使用如下&#xff1a; 先来看信号量的定义和初始化…...

完整的类在JVM中的生命周期详解

首先给出一个示例代码&#xff1a; 示例的目标是展示一个多功能的类结构&#xff0c;包含继承、接口实现、静态成员、本地方法、线程安全等特性&#xff0c;同时模拟一个简单的“计算器”场景&#xff0c;计算并管理数字。&#xff08;尽量将所有的 Java 组件和关键字都给出&am…...

Flutter中常用命令

1.检测flutter运行环境 flutter doctor 2.升级flutter flutter upgrade 3.查看flutter 版本 flutter --version 4.查看连接的设备 flutter devices 5.运行flutter项目 flutter run 或者在vscode中按FnF5 6.打包 flutter build apk //默认打release包 7.开…...

C#里使用libxl的数字格式

由于EXCEL里可以表示不同的数字格式, 比如表示货币数字时,与表示普通序号的数字就不一样。 还有科学计算表示的数字使用小数点位数与普通货币也不一样。 如下所示: 要使用这些格式, 下面创建一个例子来演示保存这些数字格式: private void button11_Click(object send…...

c#难点整理2

1.对象池的使用 就是先定义一系列的对象&#xff0c;用一个&#xff0c;调一个。 public class ObjectPool<T> where T : new(){private Queue<T> pool; // 用于存储对象的队列private int maxSize; // 对象池的最大容量// 构造函数public ObjectPool(int maxSi…...

android adjust 卸载与重装监测

想要洞察应用内用户的留存率,可以通过Adjust 的卸载与重装进行监测 名词解释: 卸载:集成完成后,卸载应用,安装状态为:卸载 重装:如果应用已经卸载,但一段时间后又进行安装,则会被视为重装。 📢📢📢:adjust 文件中说到24 小时后,可以再 adjust 控制台看安装…...

自然语言处理(5)—— 中文分词

中文分词的基本原理及实现 1. 什么是词2. 基本原理3. 发展趋势&#xff1a;多数场景无需显式分词 信息处理的目标是使用计算机能够理解和产生自然语言。而自然语言理解和产生的前提是对语言能够做出全面的解析。 汉语词汇是语言中能够独立运用的最小的语言单位&#xff0c;是语…...

解锁物联网高效开发,Synaptics SYN43756E Wi-Fi 6E 芯片登场

Synaptics 的 SYN43756E 芯片是一款高性能的 Wi-Fi 6E 支持 11a/b/g/n/ac/ax 的物联网&#xff08;IoT&#xff09;SoC&#xff0c;具备多项先进特性&#xff0c;适用于多种应用场景&#xff0c;以下是其主要优势&#xff1a; 1. 广泛的应用场景 智慧家庭&#xff1a;支持多种…...

C++和标准库速成(十二)——练习

目录 练习1.1题目答案 练习1.2题目答案 练习1.3题目答案 练习1.4题目答案 练习1.5题目答案 练习1.6题目答案 参考 练习1.1 题目 修改下面的Employee结构体&#xff0c;将其放在一个名为HR的名称空间中。你必须对main()中的代码进行那些修改才能使用此新实现&#xff1f;此外&a…...

DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能📚页面效果📚指令输入�…...

5、linux c 线程 - 上

【四】线程 1. 线程的创建 #include <pthread.h> ​ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*routine)(void *), void *arg); pthread_t *thread&#xff1a;指向线程标识符的指针&#xff0c;用于存储新创建线程的 ID。 const p…...

2024年河南省职业院校 技能大赛高职组 “大数据分析与应用” 赛项任务书(四)

2024 年河南省职业院校 技能大赛高职组 “大数据分析与应用” 赛项任务书&#xff08;四&#xff09;&#xff09; 背景描述&#xff1a;任务一&#xff1a;Hadoop 完全分布式安装配置&#xff08;25 分&#xff09;任务二&#xff1a;离线数据处理&#xff08;25 分&#xff0…...

Model Context Protocol - Prompts

1. 概述 Model Context Protocol (MCP) 提供了一种标准化的方式&#xff0c;使服务器能够向客户端暴露提示模板&#xff08;prompts&#xff09;。Prompts 是服务器提供的结构化消息和指令&#xff0c;用于与语言模型进行交互。客户端可以发现可用的提示、获取其内容&#xff…...

dify创建第一个Agent

1、首先LLM模型必须支持 Function Calling 由于deepseek-R1本地化部署时还不支持&#xff0c;所以使用 qwq模型。 2、创建空白 Agent 3、为Agent添加工具 4、测试 当未添加时间工具时 询问 时间 如下 5、开启时间工具 询问如下...