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的熟悉,需要看看源码或者文档。以及利用正则表达式对标题进行匹配

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony 开源鸿蒙北向开发——linux使用make交叉编译第三方库

这几天搞鸿蒙&#xff0c;需要编译一些第三方库到鸿蒙系统使用。 头疼死了&#xff0c;搞了一个多星期总算搞定了。 开贴记坑。 一、SDK下载 1.下载 在linux下使用命令 wget https://cidownload.openharmony.cn/version/Master_Version/OpenHarmony_5.1.0.54/20250313_02…

SVN简明教程——下载安装使用

SVN教程目录 一、开发中的实际问题二、简介2.1 版本控制2.2 Subversion2.3 Subversion的优良特性2.4 工作原理2.5 SVN基本操作 三、Subversion的安装与配置1. 服务器端程序版本2. 下载源码包3. 下载二进制安装包4. 安装5. 配置版本库① 为什么要配置版本库&#xff1f;② 创建目…

OpenCV旋转估计(1)用于估计图像间仿射变换关系的类cv::detail::AffineBasedEstimator

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 基于仿射变换的估计器。 这种估计器使用匹配器估算的成对变换来为每个相机估算最终的变换。 cv::detail::AffineBasedEstimator 是 OpenCV 库中…

大数据学习栈记——HBase安装

本文介绍大数据技术中流行的非关系型数据库HBase的安装&#xff0c;操作系统&#xff1a;Ubuntu24.04 安装Zookeeper 安装HBase前需要先安装Zookeeper&#xff0c;HBase使用Zookeeper作为其分布式协同服务&#xff0c;存储了HBase集群的元数据信息&#xff0c;并提供了分布式…

SpringBoot+VUE(Ant Design Vue)实现图片下载预览功能

目录 背景 1.后端实现下载接口 2.前端请求实现 第一步&#xff1a;导入api 第二步&#xff1a;请求接口 3.前端展示实现 4.实现效果展示 5.总结 背景 这段时间通过SpringBootVUE(Ant Design Vue)框架做了一个项目&#xff0c;但是在图片下载&#xff0c;展示的时候在网…

Java 推送钉钉应用消息

前言&#xff1a; 本文的目的是通过手机号获取钉钉成员的userid&#xff0c;实现钉钉应用的消息推送。 一、创建钉钉应用 登录钉钉开放平台 二、应用相关凭证 需要获取 Client ID (原 AppKey 和 SuiteKey) Client Secret (原 AppSecret 和 SuiteSecret) App ID 原企业内部…

SpringCloud介绍

什么是SpringCloud&#xff1f; SpringCloud 是分布式微服务架构下的一站式解决方案&#xff0c;是各个微服务架构落地技术的集合体&#xff0c;俗称微服务全家桶。 官方介绍&#xff1a; SpringCloud是基于SpringBoot提供了一套微服务解决方案&#xff0c;包括服务注册与发现…

YOLOv11 目标检测

本文章不再赘述anaconda的下载以及虚拟环境的配置&#xff0c;博主使用的python版本为3.8 1.获取YOLOv11的源工程文件 链接&#xff1a;GitHub - ultralytics/ultralytics: Ultralytics YOLO11 &#x1f680; 直接下载解压 2.需要自己准备的文件 文件结构如下&#xff1a;红…

【Linux】——环境变量与进程地址空间

文章目录 环境变量环境变量的概念常见的环境变量PATH相关指令 main的三个参数前两个参数第三个参数 程序地址空间进程地址空间 环境变量 环境变量的概念 环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;将来会以shell的形式传递给所有进程&…

Kafka--常见问题

1.为什么要使用 Kafka&#xff0c;起到什么作用 Kafka是一个高吞吐量、分布式、基于发布订阅的消息系统&#xff0c;它主要用于处理实时数据流 Kafka 设计上支持高吞吐量的消息传输&#xff0c;每秒可以处理数百万条消息。它能够在处理大量并发请求时&#xff0c;保持低延迟和…

Flutter:页面滚动,导航栏背景颜色过渡动画

记录&#xff1a;导航默认透明&#xff0c;页面发生滚动后&#xff0c;导航背景色由0-1&#xff0c;过渡到白色背景。 view import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import package:get/get.dart; import package:redo…

探秘格式化:数据危机与恢复之道

引言 在数字化飞速发展的当下&#xff0c;数据已然成为我们生活中不可或缺的一部分。无论是珍贵的家庭照片、重要的工作文档&#xff0c;还是企业关键的业务数据&#xff0c;都承载着我们的回忆、努力和希望。然而&#xff0c;格式化这一操作却如同隐藏在数字世界中的“幽灵”…

人工智能 - 通用 AI Agent 之 LangManus、Manus、OpenManus 和 OWL 技术选型

一、核心项目概览 1. Manus(闭源通用 AI Agent) 定位 :全球首个全流程自动化通用 AI Agent,GAIA 基准测试 SOTA 水平。核心能力 : 全流程自动化 :从任务规划(如撰写报告)到执行(代码生成、表格制作)的端到端处理。智能纠错机制 :基于沙箱环境的实时错误反思与调整…

封装一个分割线组件

最终样式 Vue2代码 <template><div class"sep-line"><div class"sep-label"><span class"sep-box-text"><slot>{{ title }}</slot> <!-- 默认插槽内容&#xff0c;如果没有传递内容则使用title -->&…

走进Java:String字符串的基本使用

❀❀❀ 大佬求个关注吧~祝您开心每一天 ❀❀❀ 目录 一、什么是String 二、如何定义一个String 1. 用双引号定义 2. 通过构造函数定义 三、String中的一些常用方法 1 字符串比较 1.1 字符串使用 1.2 字符串使用equals() 1.3 使用 equalsIgnoreCase() 1.4 cpmpareTo…

第2.2节 Android Jacoco插件覆盖率采集

JaCoCo&#xff08;Java Code Coverage&#xff09;是一款开源的代码覆盖率分析工具&#xff0c;适用于Java和Android项目。它通过插桩技术统计测试过程中代码的执行情况&#xff0c;生成可视化报告&#xff0c;帮助开发者评估测试用例的有效性。在github上开源的项目&#xff…

OpenGL ES ->乒乓缓冲,计算只用两个帧缓冲对象(Frame Buffer Object)+叠加多个滤镜作用后的Bitmap

乒乓缓冲核心思想 不使用乒乓缓冲&#xff0c;如果要每个滤镜作用下的绘制内容&#xff0c;也就是这个滤镜作用下的帧缓冲&#xff0c;需要创建一个Frame Buffer Object加上对应的Frame Buffer Object Texture使用乒乓缓冲&#xff0c;只用两个Frame Buffer Object加上对应的F…

Unity导出WebGL,无法加载,data文件无法找到 404(NotFound)

问题&#xff1a;data文件无法找到404Not found 示例是使用IIS托管启动 F12可以看到not found 的报错 解决办法&#xff1a; iis无法识别data文件&#xff0c;在MIME类型中增加data 类型&#xff1a;application/octet-stream 添加之后&#xff0c;会在根目录下生产一个…

C++与OO思想的联系

一、C与OO思想的联系 C&#xff1a;OO思想&#xff08;面向对象--属性和行为&#xff09; 任何事务都可以被看做一个个对象&#xff0c;一个再复杂的模型结构都是由千千万万个对象组成。 OO思想两个要素&#xff1a;属性和行为(方法)。 OO思想的特点&#xff1a; 封装&#x…

单表达式倒计时工具:datetime的极度优雅(DeepSeek)

一个简单表达式&#xff0c;也可以优雅自成工具。 笔记模板由python脚本于2025-03-22 20:25:49创建&#xff0c;本篇笔记适合任意喜欢学习的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述。 Pyth…