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

基于策略模式和简单工厂模式实现zip、tar、rar、7z四种压缩文件格式的解压

推荐语

这篇技术文章深入探讨了基于策略模式和简单工厂模式实现四种常见压缩文件格式的解压方法。通过阅读该文章,你将了解到如何利用这两种设计模式来实现灵活、可扩展的解压功能,同时适应不同的压缩文件格式。如果你对设计模式和文件处理感兴趣或刚好碰到类似的情况,那么这篇文章绝对值得一读。它会为你打开一个新的思路,并帮助你提升在软件开发中的技能和效率。

需求描述与分析

最近我遇到了一个需求,需要上传一个压缩包文件,其中包含目录和文件。上传成功后,后台会自动解压该文件,并保持压缩包内目录和文件的结构不变,然后将该结构渲染到页面上。

这个需求其实相对来说非常简单,实现起来并不困难。为了满足需求,我们需要解决以下三个问题:

  • 压缩包文件有多种格式,例如ZIP、RAR、TAR等等,我们需要支持哪些格式?
  • 如何选择合适的技术或工具来自动化地解压这些不同格式的文件?
  • 在解压压缩包的同时,如何解析出里面的目录、文件之间的关系和结构,以便被正确地渲染到前端页面上?

实现原理

先解决第一个问题:压缩包文件的格式有很多,要支持多少种?

下面这四种相对比较常见,支持解析的格式暂时定为这四种:

  • ZIP (.zip):ZIP 是最常见的压缩文件格式之一,多数操作系统都默认支持它。ZIP 文件通常用于在网络或电子邮件中传输文件,以及在本地计算机上备份和存档文件。
  • TAR (.tar):TAR 是一种用于将多个文件和文件夹打包成一个单独的文件的文件格式。与其他压缩格式不同,TAR 不会对文件进行压缩,仅用于打包和归档文件。
  • RAR (.rar):RAR 是另一种常见的压缩文件格式,它可以压缩许多文件,并提供比 ZIP 更好的压缩率。RAR 格式通常用于将大型文件分成多个部分,以便在互联网上分发和下载。
  • 7Z (.7z):7Z 是一种开源的压缩文件格式,可提供比其他压缩文件格式更高的压缩率。7Z 文件通常用于压缩大型文件和文件夹,以便在网络上传输和存储。

第二个问题:如何解压这些不同格式的文件?

支付的压缩文件的格式暂定为上面四种格式的压缩包文件那如何对这些不同格式的压缩包文件进行解压操作呢?如文章标题,基于策略模式和 简单工厂模式先实现上面四种格式的压缩文件解压,具体怎么实现呢?

  • 定义一个解压策略的抽象接口,内部定义一个抽象方法,作用是执行解压操作,但是这里不提供具体实现,具体实现由不同格式的具体解压策略来实现,这个方法的输入参数采用java标准的输入流,方便与其他业务对象,输出参数则是一个List集合类型,集合内存储的是解压文件的FileObj对象;
  • 分别根据四种压缩文件格式,定义四个不同的解压策略实现类,这四个解压策略实现类来实现上面的解压策略抽象接口,重写接口的抽象方法,方法的业务逻辑是来执行具体格式的压缩文件的解压操作;
  • 再定义一个解压策略的简单工厂类,用于根据不同的后缀,生成不同的解压策略,这个工工厂类最大的意义莫过于实现了解压客户端业务与具体解压操作的解耦;如果后续业务变更,需要新增其他格式的压缩文件解压,可以实现一个具体的解压策略类,然后再扩展一下这里的工厂类;解压客户端业务不需要做任何变更,这也符合设计模式中的单一职责;

第三个问题:压缩包文件解压的同时,怎么解析出压缩包里面的目录、文件的关系和结构?

  • 从压缩包文件中解析出文件后,解压结果是一个包含FileObj对象的集合,FileObj对象包含了三个属性:1、文件在压缩包内的全路径(包含有文件名称、后缀);2、文件后缀;3、文件的全部字节(这里封装为字节的目的是方便,后面的处理,如写入本地、写入远程文件服务器等);
  • 从解析结果中提取出文件在压缩包内的全路径;然后再进一步处理,转换为一个包含FileDir类型对象的集合,FileDir对象中有两个重要属性当前文件或目录的唯一标识和其父级的唯一标识,据此可以构建出一个树形结构,也就还原了压缩包里面的目录、文件的关第和结构;

实现方案

mavne依赖

  <dependency><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId><version>1.24.0</version></dependency><dependency><groupId>net.sf.sevenzipjbinding</groupId><artifactId>sevenzipjbinding</artifactId><version>16.02-2.01</version></dependency><dependency><groupId>org.tukaani</groupId><artifactId>xz</artifactId><version>1.9</version></dependency><dependency><groupId>com.github.junrar</groupId><artifactId>junrar</artifactId><version>7.5.5</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>net.sf.sevenzipjbinding</groupId><artifactId>sevenzipjbinding-all-platforms</artifactId><version>16.02-2.01</version></dependency><dependency><groupId>org.apache.ant</groupId><artifactId>ant</artifactId><version>1.10.12</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.23</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.32</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.6</version></dependency>

FileObj和FileDir

FileObj:从压缩包中解压出的每一个文件,封装到一个FileObj对象中,FileObj对象有三个属性:1、文件在压缩包内的全路径(包含有文件名称、后缀);2、文件后缀;3、文件的全部字节(这里封装为字节的目的是方便,后面的处理,如写入本地、写入远程文件服务器等)

@Data
public class FileObj {/*** 压缩包内文件全路径*/private String filePath;/*** 压缩包内文件后缀*/private String suffix;/*** 压缩包内文件的字节*/private byte[] bytes;
}

FileDir:把压缩包文件里的每一个目录封装成一个FileDir对象,FileDir对象包有六个属性:1、目录名称;2、目录级别,根目录为1,其子目录依次递增;3、父级目录的名称,如果是根目录,则父级目录为空;4、目录的唯一标识;5、父级目录的唯一标识;6、当前节点的孩子节点;这里注意一下要重写一个hashCode和equals方法,因为在解析压缩文件内的目录、文件的关系和结构时,使用了Set集合的去重功能;

@Data
public class FileDir{/*** 类型,1:目录;2:文件;*/private Integer docType=1;/*** 目录名称*/private String docName;/*** 目录级别,根目录为1,其子目录依次递增*/private Integer level;/*** 父级目录名称*/private String parentDocName;/*** 目录唯一标识*/private Long id;/*** 父级目录唯一标识*/private Long parentId;/*** 当前节点的孩子节点*/private List<FileDir> children;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;FileDir fileDir = (FileDir) o;if (!Objects.equals(docType, fileDir.docType)) return false;if (!Objects.equals(docName, fileDir.docName)) return false;if (!Objects.equals(level, fileDir.level)) return false;if (!Objects.equals(parentDocName, fileDir.parentDocName))return false;if (!Objects.equals(id, fileDir.id)) return false;if (!Objects.equals(parentId, fileDir.parentId)) return false;return Objects.equals(children, fileDir.children);}@Overridepublic int hashCode() {int result = docType != null ? docType.hashCode() : 0;result = 31 * result + (docName != null ? docName.hashCode() : 0);result = 31 * result + (level != null ? level.hashCode() : 0);result = 31 * result + (parentDocName != null ? parentDocName.hashCode() : 0);result = 31 * result + (id != null ? id.hashCode() : 0);result = 31 * result + (parentId != null ? parentId.hashCode() : 0);result = 31 * result + (children != null ? children.hashCode() : 0);return result;}
}

UnZipStrategy

UnZipStrategy:是解压策略的抽象接口,内部定义一个抽象方法,作用是执行解压操作,具体实现由不同格式的具体解压策略来实现,这个方法的输入参数采用java标准的输入流,方便与其他业务对象,输出参数则是一个List集合类型,集合内存储的是解压文件的FileObj对象;

public interface UnZipStrategy {List<FileObj> analysis(InputStream inputStream);
}

ZipAnalysisStrategy

ZipAnalysisStrategy:是zip格式的压缩文件的解压策略,实现UnZipStrategy抽象接口,具体来执行zip格式的压缩文件的解压操作;

@Slf4j
public class ZipAnalysisStrategy implements UnZipStrategy {@Overridepublic List<FileObj> analysis(InputStream inputStream) {List<FileObj> list = new ArrayList<>();ArchiveInputStream ais = new ZipArchiveInputStream(inputStream);ArchiveEntry entry;try {while ((entry = ais.getNextEntry()) != null) {if (!entry.isDirectory()) {FileObj fileObj = extractFile(ais, entry);list.add(fileObj);}}ais.close();inputStream.close();} catch (IOException e) {log.error("zip格式压缩文件在解压时发生错误:",e);throw new RuntimeException(e);}return list;}private FileObj extractFile(ArchiveInputStream ais, ArchiveEntry entry) throws IOException {String name = entry.getName();log.info("解析文件:{}",name);int index = name.lastIndexOf(".");String suffix = name.substring(index + 1);FileObj fileObj = new FileObj();fileObj.setFilePath(entry.getName());fileObj.setSuffix(suffix);ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int length;while ((length = ais.read(buffer)) > 0) {byteArrayOutputStream.write(buffer, 0, length);}byte[] bytes = byteArrayOutputStream.toByteArray();fileObj.setBytes(bytes);byteArrayOutputStream.close();return fileObj;}
}

TarAnalysisStrategy

TarAnalysisStrategy:是tar格式的压缩文件的解压策略,实现UnZipStrategy抽象接口,具体来执行tar格式的压缩文件的解压操作;

@Slf4j
public class TarAnalysisStrategy implements UnZipStrategy {@Overridepublic List<FileObj> analysis(InputStream inputStream) {List<FileObj> list=new ArrayList<>();FileObj fileObj;TarInputStream tarInputStream = new TarInputStream(inputStream, 1024 * 2);TarEntry entry;try {while ((entry = tarInputStream.getNextEntry()) != null) {if (!entry.isDirectory()) {fileObj=new FileObj();String name = entry.getName();int index = name.lastIndexOf(".");String suffix = name.substring(index + 1);fileObj.setFilePath(name);fileObj.setSuffix(suffix);int count;byte data[] = new byte[2048];ByteArrayOutputStream outputStream = new ByteArrayOutputStream();while ((count = tarInputStream.read(data)) != -1) {outputStream.write(data, 0, count);}byte[] byteArray = outputStream.toByteArray();outputStream.close();fileObj.setBytes(byteArray);list.add(fileObj);}}inputStream.close();tarInputStream.close();} catch (IOException e) {log.error("tar格式压缩文件在解压时发生错误:",e);throw new RuntimeException(e);}return list;}
}

SevenZAnalysisStrategy

SevenZAnalysisStrategy:是7z格式的压缩文件的解压策略,实现UnZipStrategy抽象接口,具体来执行7z格式的压缩文件的解压操作;

@Slf4j
public class SevenZAnalysisStrategy implements UnZipStrategy {@Overridepublic List<FileObj> analysis(InputStream inputStream) {List<FileObj> list = new ArrayList<>();FastByteArrayOutputStream read = IoUtil.read(inputStream);byte[] byteArray = read.toByteArray();SeekableInMemoryByteChannel seekableInMemoryByteChannel = new SeekableInMemoryByteChannel(byteArray);try {SevenZFile sevenZFile = new SevenZFile(seekableInMemoryByteChannel);// 创建输出目录SevenZArchiveEntry entry;while ((entry = sevenZFile.getNextEntry()) != null) {if (!entry.isDirectory()) {FileObj fileObj = new FileObj();String name = entry.getName();log.info("解析文件:{}",name);int index = name.lastIndexOf(".");String suffix = name.substring(index + 1);fileObj.setFilePath(name);fileObj.setSuffix(suffix);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();int len = 0;byte[] b = new byte[2048];while ((len = sevenZFile.read(b)) != -1) {outputStream.write(b, 0, len);}byte[] bytes = outputStream.toByteArray();outputStream.close();fileObj.setBytes(bytes);list.add(fileObj);}}inputStream.close();read.close();seekableInMemoryByteChannel.close();} catch (IOException e) {log.error("7z格式的压缩文件在解压时发生错误:",e);throw new RuntimeException(e);}return list;}
}

RarAnalysisStrategy

RarAnalysisStrategy:是rar格式的压缩文件的解压策略,实现UnZipStrategy抽象接口,具体来执行rar格式的压缩文件的解压操作;这个格式的压缩文件解压起来稍微有点费力,用到了一个回调RarExtractCallback类,这个RarExtractCallback类实现IArchiveExtractCallback接口,重写getStream()和setOperationResult(),来实现压缩文件的解压;

@Slf4j
public class RarAnalysisStrategy implements UnZipStrategy {@Overridepublic List<FileObj> analysis(InputStream inputStream) {try {byte[] bytes = IoUtil.readBytes(inputStream);ByteArrayStream byteArrayStream = new ByteArrayStream(bytes, false);IInArchive inArchive = SevenZip.openInArchive(null, byteArrayStream);int[] in = new int[inArchive.getNumberOfItems()];for (int i = 0; i < in.length; i++) {in[i] = i;}//使用回调函数RarExtractCallback rarExtractCallback = new RarExtractCallback(inArchive);inArchive.extract(in, false, rarExtractCallback);byteArrayStream.close();inputStream.close();return rarExtractCallback.getFileObjs();} catch (IOException e) {log.error("rar格式的压缩文件在解压时发生错误:", e);throw new RuntimeException(e);}}
}
@Slf4j
public class RarExtractCallback implements IArchiveExtractCallback {private Integer index;private IInArchive inArchive;private ByteArrayOutputStream outputStream = new ByteArrayOutputStream();@Getterprivate List<FileObj> fileObjs=new ArrayList<>();public RarExtractCallback(IInArchive inArchive) {this.inArchive = inArchive;}@Overridepublic void setCompleted(long arg0) throws SevenZipException {}@Overridepublic void setTotal(long arg0) throws SevenZipException {}@Overridepublic ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException {this.index=index;boolean isFolder = (boolean) inArchive.getProperty(index, PropID.IS_FOLDER);return data -> {if (!isFolder) {try {outputStream.write(data);} catch (IOException e) {log.error("rar格式的压缩文件在解压时发生错误:",e);throw new RuntimeException(e);}}return data.length;};}@Overridepublic void prepareOperation(ExtractAskMode arg0) throws SevenZipException {}@Overridepublic void setOperationResult(ExtractOperationResult extractOperationResult) throws SevenZipException {String path = (String) inArchive.getProperty(index, PropID.PATH);boolean isFolder = (boolean) inArchive.getProperty(index, PropID.IS_FOLDER);if (!isFolder) {FileObj fileObj=new FileObj();fileObj.setFilePath(path);log.info("解析文件:{}",path);int index1 = path.lastIndexOf(".");String suffix = path.substring(index1 + 1);fileObj.setSuffix(suffix);byte[] byteArray = outputStream.toByteArray();outputStream.reset();fileObj.setBytes(byteArray);fileObjs.add(fileObj);}}
}

UnZipStrategyFactory

UnZipStrategyFactory:解压策略的简单工厂类,用于根据不同的后缀,生成不同的解压策略,最大的意义莫过于实现了解压主业务与具体解压操作的解耦;

public class UnZipStrategyFactory {public static UnZipStrategy generate(String suffix){UnZipStrategy strategy;switch (suffix){case "zip":strategy=new ZipAnalysisStrategy();break;case "tar":strategy=new TarAnalysisStrategy();break;case "rar":strategy=new RarAnalysisStrategy();break;case "7z":strategy=new SevenZAnalysisStrategy();break;default:strategy=null;break;}return strategy;}
}

FileDirProcessor

FileDirProcessor:用于从压缩包里解压出的文件列表里,解析出目录与文件的结构,即包含FileDir对象的集合;

public class FileDirProcessor {public static List<FileDir> process(List<String> list) {//解析和去重Set<FileDir> sets = new HashSet<>();if (CollUtil.isNotEmpty(list)) {for (String dirStr : list) {String[] split = dirStr.split("/");if (split.length > 0) {if (split.length == 1) {FileDir fileDir = new FileDir();fileDir.setDocName(split[0]);fileDir.setDocType(2);fileDir.setLevel(1);fileDir.setParentDocName("");sets.add(fileDir);} else {for (int i = 0; i < split.length; i++) {FileDir fileDir = new FileDir();fileDir.setDocName(split[i]);fileDir.setLevel(i + 1);fileDir.setDocType(1);if (i == 0) {fileDir.setParentDocName("");}if (i == (split.length - 1)) {fileDir.setDocType(2);fileDir.setParentDocName(split[i - 1]);}if (i != 0 && i != split.length - 1) {fileDir.setParentDocName(split[i - 1]);}sets.add(fileDir);}}}}}if (CollUtil.isNotEmpty(sets)) {//设置idMap<String, Long> map = new HashMap<>();Snowflake snowflake = IdUtil.getSnowflake();for (FileDir fileDir : sets) {long id = snowflake.nextId();fileDir.setId(id);map.put(fileDir.getLevel() + fileDir.getDocName(), id);}//设置父idfor (FileDir fileDir : sets) {if (fileDir.getLevel() == 1) {fileDir.setParentId(0L);} else {Long parentId = map.get((fileDir.getLevel() - 1) + fileDir.getParentDocName());fileDir.setParentId(parentId);}}}return new ArrayList<>(sets);}
}

FileDirTree

FileDirTree:在FileDirProcessor类的解析结果中定义了两个关键东西,当前文件或目录的唯一标识id和父id,FileDirTree的作用用在于把FileDirProcessor类的解析结果转换成一种树形结构,以便在页面上渲染展示;

public class FileDirTree {public List<FileDir> nodeList;public FileDirTree(List<FileDir> nodeList) {this.nodeList = nodeList;}private List<FileDir> getRootNode() {List<FileDir> rootNodeList = new ArrayList<>();for (FileDir treeNode : nodeList) {if (0 == treeNode.getParentId()) {rootNodeList.add(treeNode);}}return rootNodeList;}public List<FileDir> buildTree() {List<FileDir> treeNodes = new ArrayList<FileDir>();for (FileDir treeRootNode : getRootNode()) {treeRootNode = buildChildTree(treeRootNode);treeNodes.add(treeRootNode);}return treeNodes;}private FileDir buildChildTree(FileDir pNode) {List<FileDir> childTree = new ArrayList<FileDir>();for (FileDir treeNode : nodeList) {if (treeNode.getParentId().equals(pNode.getId())) {childTree.add(buildChildTree(treeNode));}}pNode.setChildren(childTree);return pNode;}}

单元测试

    @Testpublic void test4() throws IOException {String fileName = "e:/zip/test.zip";int index = fileName.lastIndexOf(".");String suffix = fileName.substring(index + 1);//构建解压策略UnZipStrategy unZipStrategy = UnZipStrategyFactory.generate(suffix);//开始解压List<FileObj> analysis = unZipStrategy.analysis(Files.newInputStream(Paths.get(fileName)));//从解压结果中获取解压文件的全路径List<String> list = analysis.stream().map(FileObj::getFilePath).collect(Collectors.toList());
//        log.info(JSONUtil.toJsonStr(list));
//        this.saveFile(analysis, suffix);//根据解压文件的全路径解析出压缩包内文件和目录的树形结构List<FileDir> process = FileDirProcessor.process(list);FileDirTree fileDirTree = new FileDirTree(process);List<FileDir> tree = fileDirTree.buildTree();log.info(JSONUtil.toJsonStr(tree));}

源码下载

如果想获取完整的示例代码,可以从下面这个地址clone:

凡夫贩夫 / unzip-demo · GitCode

写在最后

感谢您阅读我的文章,如果您觉得我的内容对您有所启发或帮助,欢迎关注我并给我点赞。

相关文章:

基于策略模式和简单工厂模式实现zip、tar、rar、7z四种压缩文件格式的解压

推荐语 这篇技术文章深入探讨了基于策略模式和简单工厂模式实现四种常见压缩文件格式的解压方法。通过阅读该文章&#xff0c;你将了解到如何利用这两种设计模式来实现灵活、可扩展的解压功能&#xff0c;同时适应不同的压缩文件格式。如果你对设计模式和文件处理感兴趣或刚好…...

修改jenkins的目录(JENKINS_HOME)

默认JENKINS_HOME是/var/lib/jenkins/ 现要修改为/home/jenkins_data/jenkins 最开始 sudo cp -a /var/lib/jenkins/ /home/jenkins_data/ 然后如下操作&#xff1a; 1、首先 /etc/sysconfig/jenkins&#xff1a;jenkins配置文件&#xff0c;“端口”&#xff0c;“JENKIN…...

Bytebase:统一数据库 CI/CD 解决方案 | 开源日报 No.128

bytebase/bytebase Stars: 7.9k License: NOASSERTION Bytebase 是一个数据库 CI/CD 解决方案&#xff0c;为开发人员和 DBA 提供统一的工具来管理不同数据库系统的开发生命周期。其主要功能包括标准化操作流程、SQL 代码审查、GitOps 集成以及数据访问控制等。关键特性和核心…...

History对象常用方法

文章目录 一、什么是History对象二、使用History对象 一、什么是History对象 history 对象来保存浏览器历史记录信息&#xff0c;也就是用户访问的页面。浏览器的前进与后退功能本质上就是 history 的操作。history 对象记录了用户浏览过的页面&#xff0c;通过该对象提供的 A…...

修改源码,element的el-table合并,处理合并产生的hover样式问题

1、确认自己element-ui的版本号 2、此element-ui下的lib包是修改过hover样式的包,如何替换自己文件下的node_modules中的包 修改后将lib文件夹中文件替换你项目中/node_module/element-ui/Lib中的文件问题??如果替换开发环境中的node_module的包无法升级到测试环境,因为nod…...

IoT 物联网常用协议

物联网协议是指在物联网环境中用于设备间通信和数据传输的协议。根据不同的作用&#xff0c;物联网协议可分为传输协议、通信协议和行业协议。 传输协议&#xff1a;一般负责子网内设备间的组网及通信。例如 Wi-Fi、Ethernet、NFC、 Zigbee、Bluetooth、GPRS、3G/4G/5G等。这些…...

使用java备份和恢复SQLServer表数据

需求 近来工作中遇到一个问题&#xff0c;内网办公系统中的数据需要导出到外网中进行查询&#xff0c;外网的数据库中还有一些表存储外网的数据&#xff0c;因此无法使用全库备份恢复功能来满足需求。即只从内网数据库中导出若干表的内容至外网数据库的对应表。 其他解决方案…...

27 UVM queue

uvm_queue类构建一个动态队列&#xff0c;该队列将按需分配并通过引用传递。 uvm_queue类声明&#xff1a; class uvm_queue #( type T int ) extends uvm_object 1 uvm_queue class hierarchy 2 uvm_queue class Methods 3 UVM Queue Example 在下面的示例中&#xff0c;…...

聊聊自动化测试的分层实践

技术群里&#xff0c;有同学聊起了各自在实践自动化测试时遇到的各种问题&#xff0c;最典型的就是落地难度和投入产出比。毕竟在当前这个时间节点&#xff0c;单纯的技术实践如果不能带来实际可见的业务价值&#xff0c;确实很影响个人绩效和团队产出。 这篇文章&#xff0c;…...

LVS那点事

LVS 原理 IPVS LVS 的 IP 负载均衡技术是通过 IPVS 模块来实现的&#xff0c;IPVS 是 LVS 集群系统的核心软件&#xff0c;它的主要作用是&#xff1a;安装在 Director Server 上&#xff0c;同时在 Director Server 上虚拟出一个 IP 地址&#xff0c;用户必须通过这个虚拟的…...

2022-2023年度广东省职业院校学生专业技能大赛“软件测试”赛项接口测试训练题目

接口测试 新增接口脚本编写和执行测试,并执行脚本。 (1)商品单位添加接口描述如下: 接口功能:提供商品单位新增处理。 接口地址(根据实际系统IP及端口自行替换): http://XX.XX.XX.XX:XXXX/prod-api/manager/category/add。 请求方式:POST。 请求参数:...

[Python][LeetCode]28. 找出字符串中第一个匹配项的下标

给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 示例 1&#xff1a; 输入&#xff1a;haystack &quo…...

Prometheus监控mysql

docker-compose.yml 创建mysql mkdir/data/mysql -pcat > /data/mysql/docker-compose.yml << EOF version: 3.1 services:db:image: mysql:8.0restart: alwayscontainer_name: mysqlenvironment:TZ: Asia/ShanghaiLANG: en_US.UTF-8MYSQL_ROOT_PASSWORD: 123456comm…...

骑砍战团MOD开发(30)-游戏大地图map.txt

骑砍1战团mod开发-大地图制作方法_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1rz4y1c7wH/ 一.骑砍游戏大地图 骑砍RTS视角游戏大地图 大地图静态模型(map.txt) 军团/城镇图标(module_parties.py). 骑砍大地图的战争迷雾和天气通过API进行管理和控制: # Weather-h…...

关于 bringup sensor 时,曝光时间异常的问题排查

1、问题背景 这两天在配置 sc223a 这颗 sensor 的驱动&#xff0c;按 datasheet 的要求配置 sensor 的曝光后&#xff0c;发现最大曝光时间增加了一倍&#xff0c; sensor setting 用的是30fps &#xff0c;理论上最大的绝对曝光时间应该是 33ms 才正确&#xff0c;但实际用 …...

linux用户态与内核态通过字符设备交互

linux用户态与内核态通过字符设备交互 简述 Linux设备分为三类&#xff0c;字符设备、块设备、网络接口设备。字符设备只能一个字节一个字节读取&#xff0c;常见外设基本都是字符设备。块设备一般用于存储设备&#xff0c;一块一块的读取。网络设备&#xff0c;Linux将对网络…...

如何高效查询文件:Linux 下的多种方法详解

如何高效查询文件&#xff1a;Linux 下的多种方法详解 在日常工作中&#xff0c;我们经常需要查找文件&#xff0c;无论是寻找特定的代码文件、配置文件还是其他文档。Linux 提供了多种强大的命令和工具&#xff0c;通过巧妙地使用管道符&#xff0c;我们可以将这些命令组合起来…...

记矩阵基础概念

转自up&#xff1a;Naruto_Qcsdn&#xff1a;三维空间几何变换矩阵 先贴个站里分享的基础概念。 learn form 肥猫同学VFX b站&#xff1a;会用transform就会用矩阵 移动 旋转 缩放 1.transofrm ——输出变化矩阵 可以移动transform查看变化去理解 位移 缩放 旋转 由此—…...

用html,js和layui写一个简单的点击打怪小游戏

介绍&#xff1a; 一个简单的打怪小游戏&#xff0c;点击开始游戏后&#xff0c;出现攻击按钮&#xff0c;击败怪物后可以选择继续下一关和结束游戏。 继续下一个怪兽的血量会增加5点&#xff0c;攻击按钮会随机变色。 效果图&#xff1a; html代码&#xff1a; <!DOCTYPE…...

[线代]不挂科猴博士

行列式的性质 行列式的计算及应用 矩阵的运算上(加减,相乘,取行列式) 矩阵的运算下(转置,逆,秩) 向量组与线性空间 解方程组...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...