目的:实现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. npm i和npm_让您的NPM套件包含Jest和Codecov☂️
  2. mysql帐号,权限管理
  3. python强大体现在哪些方面-什么python的if语句?它主要应用在哪些方面?
  4. java 套娃_【leetcode编程题目354】俄罗斯套娃
  5. 一级计算机综合训练第五卷,2018职称计算机考试基础综合练习及答案(5)
  6. python观察日志(part6)--不可变的元祖
  7. 上传到SAP云平台CloudFoundry上的nodejs应用存储的绝对路径
  8. mac 卸载编辑器卸不干净
  9. 光流估计——从传统方法到深度学习
  10. 最长公共子序列模板(LCS)和LICS模板
  11. OCR之Tesseract使用
  12. 设计模式系列——三个工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)...
  13. 黑马程序员Python教程的代码--植物大战僵尸游戏代码
  14. linux安装阵列卡驱动程序,linux 安装阵列卡驱动
  15. TQ2440——NandFlash分区修改
  16. 百度校招小结:我做技术面试官的一些思考
  17. 计算机组成原理中men,东北大学秦皇岛分校计算机组成原理课程设计.doc
  18. mysql是一个大型数据库_MySQL是一个大型关系型数据库管理系统(RDBMS)。
  19. 穷人跨越阶层有多难?
  20. BLAST Database error: No alias or index file found for protein database

热门文章

  1. 2月28日云栖精选夜读:用人工智能提升营销效率,阿里妈妈启动2018国际广告算法大赛
  2. java实现画笔的画圆与矩形功能_Java实现画线、矩形、椭圆、字符串功能
  3. 入职阿里巴巴,成为年薪百万阿里P7高级架构师需要必备哪些技术栈
  4. 【Unity3D日常开发】Unity3D中设置Image中的Color的值
  5. 【经理人领导力突破训练营】经理人必修课,如何成为成功的经理人?
  6. 人民币大写的正确写法
  7. No rule to make target `control'. Stop.错误解决
  8. 微信小程序轮播中的current_手把手教你美化微信小程序中的轮播效果
  9. laydate点击输入框闪一下不见了_ps文字工具打字不显示,应该如何解决?
  10. python统计红楼梦人物出场次数_《红楼梦》人数统计,人物,出场,次数