目的:实现7Z格式自解压包再不解压的情况下对条目内容读取以及复写。

首先了解7Z格式自解压包。

sfx文件通常为二进制文件,用作压缩解压软件的自解压程序模板。其实就是一个exe程序,组成格式如上

主要分为三部分:

  1. sfx文件打头,这是一个真正的程序,实现了根据config.txt配置信息解压缩尾部的压缩文件,并执行相应的操作
  2. config.txt文件做相关的配置,比如标题,解压缩位置,解压缩之后执行什么样的操作等
  3. 压缩文件,这里是真正的数据内容啦
    查看config.txt内容,一些配置信息
;!@Install@!UTF-8!Title="Software 7.00"BeginPrompt="Do you want to install the Software 7.00?"RunProgram="7zr.exe b";!@InstallEnd@!
经过测试发现,这种自解压包无法通过ZipFile类或者SevenZFile类创建对象,所以java代码无法直接对其进行操作(可以当做普通文件下载)。所以需要先对这类自解压包进行拆分,拿到我们真正需要的压缩文件。由上面信息可以知道config.txt内容最后一段为";!@InstallEnd@!",所以我们要截取这段字符之后的内容就是我们真正需要处理的压缩包。查找这段字符以及进行包的拆分操作的代码如下:

1、先找到这段字符所在位置pos。(targetFile为我们需要拆分的自解压文件):

    final byte[] encoded = ";!@InstallEnd@!".getBytes("ISO-8859-1");final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(targetFile));// sfx假定大于124,928
//    bis.skip(124928);int b;long pos = 0;int macth = 0;while ((b = bis.read()) != -1) {pos++;if (encoded[macth] == b) {macth++;} else {macth = 0;}if (macth == 15) {System.out.print(pos);break;}}bis.close();

2、然后根据这个pos来拆分文件,前面部分拆分为sfx.tmp,后半部分拆为z7.7z文件:

  //一个字节通道保持当前位置,允许位置被改变。SeekableByteChannel exeSbc = Files.newByteChannel(targetFile.toPath(), StandardOpenOption.READ);final ByteBuffer sfxBf = ByteBuffer.allocate((int) pos);final File sfxFile = new File(downloadPath + SLASH + "sfx.tmp");SeekableByteChannel sfxSbc = Files.newByteChannel(sfxFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);//在该通道的当前位置开始读取字节,然后用实际读取的字节数进行更新。exeSbc.read(sfxBf);/*flip():Buffer有两种模式,写模式和读模式。在写模式下调用flip()之后,Buffer从写模式变成读模式。也就是说调用flip()之后,读/写指针position指到缓冲区头部,并且设置了最多只能读出之前写入的数据长度(而不是整个缓存的容量大小)。*/sfxBf.flip();sfxSbc.write(sfxBf);sfxBf.clear();File z7File = new File(downloadPath + SLASH + "z7.7z");SeekableByteChannel z7Sbc = Files.newByteChannel(z7File.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);final ByteBuffer z7Bf = ByteBuffer.allocate(1024 * 1024 * 2);int i = 0;while ((i = exeSbc.read(z7Bf)) > 0) {z7Bf.flip();z7Sbc.write(z7Bf);z7Bf.clear();}z7Sbc.close();exeSbc.close();

拆分完文件,然后对7z压缩包进行读取复写操作

3、读取条目,并新建一个文件写入xml内容(targetFile为7z压缩包,SLASH为目录分隔符,downloadPath为文件路径)

try {//创建7z压缩包对象.SevenZFile zf = new SevenZFile(targetFile);//获取压缩包内条目数组.Iterable<SevenZArchiveEntry> enumeration = zf.getEntries();//遍历条目数组.for (SevenZArchiveEntry sevenZArchiveEntry : enumeration) {if ("MonitorConfig.config".equals(sevenZArchiveEntry.getName())) {//获取当前微服务的信息String address = "/necp/mapp/rpa";final ServerInfo rpaServerInfo = Mapp.INSTANCE.getServerInfo(address);//获取要读取条目的大小int size = (int) sevenZArchiveEntry.getSize();if (size > 0) {//对需要读取的条目创建字符流缓冲区BufferedReader br = new BufferedReader(new InputStreamReader(zf.getInputStream(sevenZArchiveEntry)));String str = "";String strTemp;String line;//按行读取,并替换掉换行符while ((line = br.readLine()) != null) {strTemp = line.replaceAll("\t", "");str = str + strTemp;}//把读取的字符串格式转为xml格式,并进行替换内容操作SAXReader saxReader = new SAXReader();Document document = saxReader.read(new ByteArrayInputStream(str.getBytes("UTF-8")));Iterator it = document.getRootElement().elementIterator();Element ele;Element element;while (it.hasNext()) {ele = (Element) it.next();Iterator iterator = ele.elementIterator();while (iterator.hasNext()) {element = (Element) iterator.next();if (element.attribute(0).getValue().equals("host")) {element.attribute(1).setValue(rpaServerInfo.getIpAddress());}if (element.attribute(0).getValue().equals("port")) {element.attribute(1).setValue(rpaServerInfo.getPort() + rpaServerInfo.getContextPath() + SLASH);}if (element.attribute(0).getValue().equals("scheme")) {element.attribute(1).setValue(protocol);}}}OutputFormat format = OutputFormat.createPrettyPrint();//创建xml格式的文件,并写入处理过的内容XMLWriter writer = new XMLWriter(new FileWriter(downloadPath + SLASH + "MonitorConfig.config"), format);writer.write(document);writer.close();}}}} catch (Exception e) {e.printStackTrace();
}

4、把新生成的xml内容覆写入7z压缩包(替换原有文件内容)(downloadPath为文件路径,SLASH为系统目录分隔符)

final String targetFile = downloadPath + SLASH + "z7.7z";
final String newFile = downloadPath + SLASH + "temp.7z";
final String configFile = downloadPath + SLASH + "MonitorConfig.config";
final SevenZFile zFile = new SevenZFile(new File(targetFile));
final File newzFile = new File(newFile);
if (!newzFile.exists()) {newzFile.createNewFile();
}final SevenZOutputFile outArchive = new SevenZOutputFile(newzFile);
outArchive.setContentCompression(SevenZMethod.COPY);
// 原始压缩文件处理,把原有文件复制到新建临时7Z压缩包
SevenZArchiveEntry entry;
byte[] buf = new byte[1024 * 1024 * 2];
int len;
while ((entry = zFile.getNextEntry()) != null) {if (!entry.isDirectory()) {outArchive.putArchiveEntry(entry);while ((len = zFile.read(buf)) != -1) {outArchive.write(buf, 0, len);}outArchive.closeArchiveEntry();}
}// 添加或覆盖的文件,相同文件名即覆盖。
final SevenZArchiveEntry xmlEntry = new SevenZArchiveEntry();
xmlEntry.setName("MonitorConfig.config");
outArchive.putArchiveEntry(xmlEntry);
String str = "";
try {FileInputStream fileInputStream = new FileInputStream(configFile);ByteArrayOutputStream bos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int length;while ((length = fileInputStream.read(buffer)) != -1) {bos.write(buffer, 0, length);}str = bos.toString();bos.close();fileInputStream.close();} catch (Exception e) {e.printStackTrace();
}
outArchive.write(str.getBytes());
outArchive.closeArchiveEntry();
outArchive.finish();
outArchive.close();

5、把新建临时7z压缩包和原来拆分的sfx.tmp文件合并成新的exe包(downloadPath为文件路径,SLASH为系统目录分隔符)

//sfx+config + 新的7z文件成exe.
final File robotPathFile = new File(downloadPath);
final File[] files = robotPathFile.listFiles();
//找到原有exe文件
File exeFile = null;
for (File file : files) {if (file.getName().toLowerCase().endsWith(".exe")) {exeFile = file;}
}
//删除exe文件
exeFile.delete();
//新建一个同名空exe文件
if (!exeFile.exists()) {exeFile.createNewFile();
}//先写入sfx文件
final SeekableByteChannel sbc = Files.newByteChannel(exeFile.toPath(), StandardOpenOption.APPEND);
final ByteBuffer sfxBf = ByteBuffer.wrap(FileUtils.readFileToByteArray(new File(downloadPath + SLASH + "sfx.tmp")));
sbc.write(sfxBf);
//写入新建的临时7z文件
File new7zFile = new File(newFile);
SeekableByteChannel z7Sbc = Files.newByteChannel(new7zFile.toPath(), StandardOpenOption.READ);
final ByteBuffer z7Bf = ByteBuffer.allocate(1024 * 1024 * 2);
int i = 0;
while ((i = z7Sbc.read(z7Bf)) > 0) {z7Bf.flip();sbc.write(z7Bf);z7Bf.clear();
}
z7Sbc.close();
sbc.close();
//删除临时文件.
File file = new File(targetFile);
File sfxFile = new File(downloadPath + SLASH + "sfx.tmp");
file.delete();
newzFile.delete();
sfxFile.delete();

到此就完成了读取7Z自解压包条目,然后修改读取内容再覆写入自解压文件的操作。

关于7Z自解压文件拆分,读取条目,复写,合并的功能相关推荐

  1. exl文件中数据分组去重合并的功能实现

    近期工作中遇到一个问题,一个EXL文件中含有大量数据,A列是分组名,B列是数据标识码名,C列以后都是对应的数据.表格内容如下: 想实现把串码号和商品号两列交叉重复的数据,即没组中对应的商品如果在其他组 ...

  2. java读取系统中指定的文件_java读取jar中指定的文件

    Java 档案 (Java Archive, JAR) 文件是基于 Java 技术的打包方案.它们允许开发人员把所有相关的内容 (.class.图片.声音和支持文件等) 打包到一个单一的文件中.JAR ...

  3. java读取 info.plist源码_Java 解析 IPA 文件,读取 Info.plist 信息-Go语言中文社区

    在做移动MDM功能的时候,就遇到了这样一个问题,当用户上传IPA文件时,我如何知道这个IPA文件的相关信息呢?IPA文件有一个很重要的文件Info.plist 就类似于Android程序的Manife ...

  4. 机器学习——文件的读取

    机器学习--文件的读取 (一).txt文件的读取 (二)excel文件读取操作 (一).txt文件的读取 txt的链接 链接:https://pan.baidu.com/s/1fIAUdCDTpR7T ...

  5. 大文件拆分小文件求top_将文件拆分为流

    大文件拆分小文件求top 上周,我讨论了类Pattern新的(@since 1.8)方法splitAsStream只能根据流的需要从字符序列中读取字符序列,并且不能继续进行模式匹配以创建所有可能的元素 ...

  6. python 导入数据对不齐_[Python] 大文件数据读取分析

    首先我们可以确定的是不能用read()与readlines()函数: 因为如果将这两个函数均将数据全部读入内存,会造成内存不足的情况. 针对数据按行划分的文件 以计算行数为例,首先针对几种不同的方法来 ...

  7. 7z SFX Builder v2.3.1 7Z自解压生成器中文版

    前言 7z SFX Builder是一款7Z自解压生成器,这款自解压程序制作工具是在7-Zip自解压模块7z SFX的基础上开发,可以轻松创建7z SFX配置文件,生成自解压形式EXE可执行文件,可以 ...

  8. Tableau学习Step2一数据文件的读取与统计图、表的概述

    Tableau学习Step2一数据文件的读取与统计图.表的概述 本文首发于博客冰山一树Sankey,去博客浏览效果更好. 一. 前言 本教程通过一个案例从浅到深来学习Tableau知识 案例概述: 二 ...

  9. linux如何压缩为gz文件,将一个.gz文件拆分为多个1GB压缩(.gz)文件

    我在Linux上有一个250GB的压缩文件,我想将它拆分为250个1GB文件,并在运行时压缩生成的部分文件(只要一个文件被生成,它应该被压缩). 我试图用这个 -将一个.gz文件拆分为多个1GB压缩( ...

最新文章

  1. 浅析Block的内部结构 , 及分析其是如何利用 NSInvocation 进行调用
  2. Python中re.sub()实现替换文本字符串
  3. 一篇文章了解架构师能力模型
  4. mysql 回滚段_MySQL和PostgreSQL比较
  5. android水印添加水印,android 增加背景文字 水印效果(仿钉钉)
  6. Java基础学习总结(124)——Java9逆天的十大新特性
  7. 印象笔记不同步(EDAMSystemException: errorCode=INTERNAL_ERROR)
  8. shell 面试题 (一) 待续
  9. el表达式跟ognl表达式的区别(用法和页面取值)
  10. 酷应用背后,低代码正在被重估
  11. VS985破解电信4G或联通4G
  12. 一款用C++语言实现的3D游戏引擎(附源码),适用于想学3D游戏开发
  13. CAT分布式监控系统(一):CAT功能介绍 CAT监控系统是什么、能做什么?
  14. Ansible(十四)-- ansible 中的变量(三) set_fact 模块 注册变量实现跨play调用变量
  15. element-ui MessageBox弹框确定和取消位置(this.$confirm)
  16. 计算机cpu风扇不转怎么办,计算机CPU风扇不转怎么办
  17. 纯干货:分享一些跨境电商客服经常会用到的话术(含中英文)
  18. P3332 [ZJOI2013]K大数查询 - 整体二分-区间修改
  19. [C语言]程序改错题。爱因斯坦曾出过这样的一道数学题:有一条长阶梯,若每步跨2阶,最后剩下1阶;若每步跨3阶,最后剩下2阶;若每步跨5阶,最后剩下4阶;若每步跨6阶,最后剩下5阶;只有每步跨7阶...
  20. World Locking Tools for Unity (二)背景部分

热门文章

  1. 小米路由器编程器强刷breed,可用于救砖,恢复官方系统,恢复SN
  2. ROS2极简总结-文件系统
  3. java qq聊天界面_【附源码】用Java写了一个类QQ界面聊天小项目,可在线聊天!...
  4. html保留数据库文本格式,以html格式显示数据库中的格式化文本(FLASK应用程序)...
  5. 微商如何通过自媒体平台进行引流
  6. 推荐综述博客网址马克
  7. C++程序设计基础之(第三章)函数
  8. Win10启动文件夹在哪里,Win10怎么添加开机启动项?
  9. 机器学习模型 非线性模型_pycaret在几分钟内准备好您的机器学习模型
  10. windows mobile数据同步方案