当前位置: 首页 > 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…...

[线代]不挂科猴博士

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

扩散式过滤器 水泵角通除污器 0阻力过滤器直角过滤器工作原理

​ 1&#xff1a;扩散式除污器过滤器介绍 扩散除污器是一种在多个领域都有应用的设备&#xff0c;例如在泵站中用于拦截介质中的杂质&#xff0c;净化介质&#xff0c;保护管路&#xff0c;提高水泵效率&#xff0c;延长水泵寿命等。它还可以方便地进行变径处理&#xff0c;可以…...

MetalLB:本地Kubernetes集群的LoadBalancer负载均衡利器

背景 在本地集群进行测试时&#xff0c;我们常常面临一个棘手的问题&#xff1a;Service Type不支持LoadBalancer&#xff0c;而我们只能选择使用NodePort作为替代。这种情况下&#xff0c;我们通常会配置Service为NodePort&#xff0c;并使用externalIPs将流量导入Kubernetes…...

C++判定终端ip和目标ip是否在同一局域网内

程序如下&#xff1a;用于判断给定的终端 IP、子网掩码和目标 IP 是否在同一局域网内。请注意&#xff0c;这个程序假设 IP 地址是用整数表示的。 #include <iostream> #include <sstream> #include <vector> #include <bitset>// Function to check …...

深入解析 可空值类型

前言&#xff1a; 问&#xff1a;为什么会有可空值类型的诞生&#xff1f; 答&#xff1a;应对在某些特定场景中获取的信息可能是不完整的。 C# 1中的可空值类型 在C#1中没有对应的表示Null值的方法。当时普遍都是采用其他方式。第一种在数据缺失的情况下给其一个默认值。第…...

esp32idf使用thingscloud例程

对于不同的消息类型&#xff0c;API 如下&#xff1a; 消息类型 HTTP Method HTTP URL 设备上报属性 POST /device/v1//attributes 设备获取属性 GET /device/v1//attributes 设备上报事件 POST /device/v1//event/report 您只需要将以上的 HTTP URL 和接入点拼接即可获得最终…...

记一次应急响应练习(Linux)

记一次应急响应练习(Linux) Linux&#xff1a; 请提交攻击者的IP地址 答&#xff1a; 192.168.31.132 思路&#xff1a; 通过查看历史命令和开放的8080端口看到这台主机上运行的是Tomcat服务。并且在历史命令中看到了Tomcat的安装路径。那么就算是找到了日志的查看点了&#x…...

Pandas教程(四)—— 分层索引及数据联合

1.分层索引 分层索引就是在一个轴上拥有多个&#xff08;两个及以上&#xff09;索引级别&#xff0c;能以低维度形式处理高维度数据。 行索引有两层 1.1 分层索引的创建 1.1.1 方式一&#xff1a;直接设置 1&#xff09;在创建series、dataframe或读取文件时时&#xff0c;行…...

小梅哥Xilinx FPGA学习笔记16——FSM(状态机)的学习

目录 一、 状态机导读 1.1 理论学习 1.2 状态机的表示 1.3 状态机编码 1.4 状态机描述方式 二 、实战演练一&#xff08;来自野火&#xff09; 2.1 实验目标 2.2 模块框图 2.3 状态转移图绘制 2.4 设计文件 2.5 仿真测试文件 2.6 仿真结果 三、 实战演练二&…...

vol----学习随记!!!

目录 一、代码生成1.先新建一个功能的对应的代码配置各项解释&#xff1a; 2.后设置配置菜单3.再点保存&#xff0c;生成vue页面&#xff0c;生成model&#xff0c;生成业务类4.再通过菜单设置编写系统菜单 一、代码生成 1.先新建一个功能的对应的代码配置 各项解释&#xff…...

HarmonyOS4.0系统性深入开发10卡片事件能力说明

卡片事件能力说明 ArkTS卡片中提供了postCardAction()接口用于卡片内部和提供方应用间的交互&#xff0c;当前支持router、message和call三种类型的事件&#xff0c;仅在卡片中可以调用。 接口定义&#xff1a;postCardAction(component: Object, action: Object): void 接口…...

openGauss学习笔记-181 openGauss 数据库运维-升级-升级流程

文章目录 openGauss学习笔记-181 openGauss 数据库运维-升级-升级流程 openGauss学习笔记-181 openGauss 数据库运维-升级-升级流程 本章介绍升级到该版本的主要升级过程。 图 1 升级流程图 说明&#xff1a; 本文档中描述的时间仅供参考&#xff0c;实际操作时间以现场情况…...

提前应对威胁

通过新的《2023-2028 年荷兰国际网络安全战略》&#xff0c;荷兰政府在面对国家和犯罪分子持续构成的网络威胁时展现了责任和机构。它渴望将民主、人权和规范放在首位&#xff0c;并寻求维护全球开放、自由和安全的互联网。该战略明确了政府在国内实施打击的意愿和能力&#xf…...

C语言与人生:数组交换和二分查找

少年们&#xff0c;大家好。我是博主那一脸阳光&#xff0c;今天和分享数组交换和二分查找。 前言&#xff1a;探索C语言中的数组交换操作与二分查找算法 在计算机编程领域&#xff0c;特别是以C语言为代表的低级编程语言中&#xff0c;对数据结构的理解和熟练运用是至关重要的…...

Python实现【亚马逊商品】数据采集

前言 亚马逊公司&#xff0c;是美国最大的一家网络电子商务公司&#xff0c;位于华盛顿州的西雅图 是网络上最早开始经营电子商务的公司之一&#xff0c;亚马逊成立于1994年 今天教大家用Python批量采集亚马逊平台商品数据&#xff08;完整代码放在文末&#xff09; 地址&#…...

Git使用教程 gittutorial

该教程对该文章的翻译&#xff1a;https://git-scm.com/docs/gittutorial 本文介绍怎用使用 Git 导入新的工程、修改文件及如何其他人同步开发。 首先&#xff0c; 可以使用以下指令获取文档帮助 git help log笔者注&#xff1a;不建议看这个文档&#xff0c;标准的语法介绍…...

有了向量数据库,我们还需 SQL 数据库吗?

“除了向量数据库外&#xff0c;我是否还需要一个普通的 SQL 数据库&#xff1f;” 这是我们经常被问到的一个问题。如果除了向量数据以外&#xff0c;用户还有其他标量数据信息&#xff0c;那么其业务可能需要在进行语义相似性搜索前先根据某种条件过滤数据&#xff0c;例如&a…...

信息网络协议基础-IPv6协议

文章目录 概述为什么引入IP服务模型IPv4的可扩展性问题解决方法***CIDR(Classless Inter-Domain Routing, 无类别域间寻路)前缀汇聚***前缀最长匹配***NAT(网络地址转换)存在的问题解决方案路由表配置***局限性IPv6协议头标IPv6地址表示前缀类型单播地址链路局部地址(Link-Loca…...

VC++ ado 实现单表CURD

继续修改前文的资产管理源码; 新建一个数据库sds;把代码中的数据库连接改为连接此库; 新建下图一个表; 把之前的资产类别管理对话框改为下图所示;对话框ID也改为下图; 资产类别管理菜单和ID改为下图; 直接修改资产类别管理对话框类不太方便,新建一个对话框类,没有关联…...

C#使用switch多路选择语句判断何为季节

目录 一、 switch语句 二、示例 三、生成 一、 switch语句 switch语句是多路选择语句&#xff0c;它通过一个表达式的值来使程序从多个分支中选取一个用于执行的分支。 switch表达式的值只可以是整型、字符串、枚举和布尔类型。 switch语句中多个case可以使用一个break。 在…...

可爱的魔法曲线 Lovely Magical Curves(12年开始只有5个人AC)

一起来交流编程吧&#xff01;【CSDN app】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&k3svdDJTlkD76TRRShbxYCYK1zK1c8cyF&authKeyv1pxp6rS8AA4SRy7bflJl9LIwp8d5v0HOudw%2BDxHiWDRqZ1LzjeoBJH1Z1EXnl35&noverify0&group_code546881376 可爱的魔法…...

通过C++程序实现光驱的自动化刻录和读取

文章目录 ISO文件格式光盘的基本概念光盘种类特点DVDR光盘使用windows调用Linux调用Linux平台下用到的C库:读取设备驱动列表向光驱中写文件 数字存储媒体快速发展的今天&#xff0c;光驱的使用已经不像以前那样普及了。但是在数据备份、安装软件和操作系统、旧设备兼容等领域还…...

【电商项目实战】商品详情显示与Redis存储购物车信息

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《电商项目实战》。&#x1f3af;&#x1f3af; &am…...

概率论基础

1.概率论 1.1 随机事件与概率 1.1.1 基本概念 ​ 样本点(sample point)&#xff1a; 称为试验 S S S的可能结果为样本点&#xff0c;用 ω \omega ω表示。 ​ 样本空间(sample space)&#xff1a;称试验 S S S的样本点构成的集合为样本空间&#xff0c;用 Ω \Omega Ω表示…...

Mac电脑CMake安装和配置

1.从CMake官网下载dmg文件并且安装 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a43f1462b5f743b4ba0bf5302ee76066.png)...

FormData传送复杂数据

FormData 是一个用于创建表单数据对象的 JavaScript 类。它通常用于通过 JavaScript 发送表单数据&#xff0c;尤其是用于发送 AJAX 请求时非常有用。 使用 FormData 可以方便地构建一个以 multipart/form-data 格式提交的表单数据&#xff0c;这允许你在发送 XMLHttpRequest …...

力扣回溯算法-电话号码的字母组合

力扣第17题&#xff0c;电话号码的字母组合 题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 .电话号码的字母组合 示例: 输入&#xff1a;“2…...

运维面试笔试题

目录 shell脚本 nginx 数据库mysql k8s(kubernetes) 安全与防护 网络TCP/IP shell脚本 1 通过正则表达式匹配文本...

Oracle database 静默安装 oracle12c 一键安装 12.1.0.2

基于oracle安装包中应答文件实现一键安装 注意此安装脚本基于12.1.0.2 安装包 原始安装包结构为两个压缩包 此脚本使用安装包为原始压缩包解压后、 重新封装为一个.zip压缩包 建议在linux 环境下解压重新压缩后 使用该脚本 支持环境: Linux :centerOS 7 oracle :12.1.0.…...

【Java EE初阶三 】线程的状态与安全(上)

1. join方法与多线程 1.1 初识多线程 为了提高cpu得利用率&#xff0c;因此就引入了多个线程的概念&#xff1b;即每个线程负责完成整个程序的一部分工作即可。 写一个代码&#xff0c;让主线程&#xff0c;创建一个新的线程&#xff0c;由新线程负责完成运算&#xff08;12。…...

英飞凌TC3xx之一起认识GTM系列(五)如何实现GTM与DSADC关联的配置

英飞凌TC3xx之一起认识GTM系列(五)如何实现GTM与DSADC关联的配置 1 GTM与DSADC的连接1.1 EDSADC 到 GTM 的连接1.1.1 工作原理说明1.1.2 应用举例1.2 GTM 到 EDSADC 的连接1.2.1 工作原理说明1.2.2 应用举例2 总结编者按:笔者在从事这部分开发工作的时候,看着手册上的各种通…...