前言
因为之前开发过APP移动端的应用发布平台,移动端的配置文件解析都有相应的解析工具,从而想为啥不能开发个EXE程序管理平台把三种类型的文件放到同一个项目进行管理,且走相同的逻辑代码?
有目标了,开搞!!!!
首先网上百度EXE解析配置文件工具…嗯 基本没有,不太好写,先看EXE文件包
压缩文件结构
配置文件结构内容纯json配置
这里我们需要读取json文件里面的项目名称productName、appId、version版本、description项目描述
好了完事具备,只欠代码了…哦还差一步 ——依赖!依赖!依赖!
<!-- https://mvnrepository.com/artifact/net.sf.sevenzipjbinding/sevenzipjbinding 7z解压工具主要依赖 -->
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding</artifactId>
<version>16.02-2.01</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.sevenzipjbinding/sevenzipjbinding-all-windows 7Z解压window兼容初始化工具-->
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding-all-windows</artifactId>
<version>16.02-2.01</version>
</dependency>
下面就是主体代码了:
package com.djcps.avm.commons.utils;
import com.djcps.log.DjcpsLogger;
import com.djcps.log.DjcpsLoggerFactory;
import org.apache.logging.log4j.core.util.Throwables;
import net.sf.sevenzipjbinding.ExtractAskMode;
import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.IArchiveExtractCallback;
import net.sf.sevenzipjbinding.ISequentialOutStream;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.util.regex.Pattern;
/**
* @program: djapp-master
* @description: //直接读取exe文件的版本信息
* @author: Mr.Wang
* @create: 2020-03-13 10:09
**/
public class ZipUtils {
private static DjcpsLogger LOGGER = DjcpsLoggerFactory.getLogger(ZipUtils.class);
/**
* 获取.exe文件的版本信息
* @param file
* @return
*/
public static String getVersion(File file) {
byte[] buffer;
String str;
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file, "r");
buffer = new byte[64];
raf.read(buffer);
str = "" + (char) buffer[0] + (char) buffer[1];
if (!"MZ".equals(str)) {
return null;
}
int peOffset = unpack(new byte[]{buffer[60], buffer[61], buffer[62], buffer[63]});
if (peOffset < 64) {
return null;
}
raf.seek(peOffset);
buffer = new byte[24];
raf.read(buffer);
str = "" + (char) buffer[0] + (char) buffer[1];
if (!"PE".equals(str)) {
return null;
}
int machine = unpack(new byte[]{buffer[4], buffer[5]});
if (machine != 332) {
return null;
}
int noSections = unpack(new byte[]{buffer[6], buffer[7]});
int optHdrSize = unpack(new byte[]{buffer[20], buffer[21]});
raf.seek(raf.getFilePointer() + optHdrSize);
boolean resFound = false;
for (int i = 0; i < noSections; i++) {
buffer = new byte[40];
raf.read(buffer);
str = "" + (char) buffer[0] + (char) buffer[1] +
(char) buffer[2] + (char) buffer[3] + (char) buffer[4];
if (".rsrc".equals(str)) {
resFound = true;
break;
}
}
if (!resFound) {
return null;
}
int infoVirt = unpack(new byte[]{buffer[12], buffer[13], buffer[14], buffer[15]});
int infoSize = unpack(new byte[]{buffer[16], buffer[17], buffer[18], buffer[19]});
int infoOff = unpack(new byte[]{buffer[20], buffer[21], buffer[22], buffer[23]});
raf.seek(infoOff);
buffer = new byte[infoSize];
raf.read(buffer);
int numDirs = unpack(new byte[]{buffer[14], buffer[15]});
boolean infoFound = false;
int subOff = 0;
for (int i = 0; i < numDirs; i++) {
int type = unpack(new byte[]{buffer[i * 8 + 16], buffer[i * 8 + 17], buffer[i * 8 + 18], buffer[i * 8 + 19]});
if (type == 16) {
infoFound = true;
subOff = unpack(new byte[]{buffer[i * 8 + 20], buffer[i * 8 + 21], buffer[i * 8 + 22], buffer[i * 8 + 23]});
break;
}
}
if (!infoFound) {
return null;
}
subOff = subOff & 0x7fffffff;
infoOff = unpack(new byte[]{buffer[subOff + 20], buffer[subOff + 21], buffer[subOff + 22], buffer[subOff + 23]});
infoOff = infoOff & 0x7fffffff;
infoOff = unpack(new byte[]{buffer[infoOff + 20], buffer[infoOff + 21], buffer[infoOff + 22], buffer[infoOff + 23]});
int dataOff = unpack(new byte[]{buffer[infoOff], buffer[infoOff + 1], buffer[infoOff + 2], buffer[infoOff + 3]});
dataOff = dataOff - infoVirt;
int version1 = unpack(new byte[]{buffer[dataOff + 48], buffer[dataOff + 48 + 1]});
int version2 = unpack(new byte[]{buffer[dataOff + 48 + 2], buffer[dataOff + 48 + 3]});
int version4 = unpack(new byte[]{buffer[dataOff + 48 + 6], buffer[dataOff + 48 + 7]});
return version2 + "." + version1 + "." + version4 ;
} catch (Exception e) {
LOGGER.error("文件{}版本号解析失败!错误信息:{}", file.getAbsolutePath(), Throwables.getRootCause(e));
return null;
} finally {
if (raf != null) {
try {
raf.close();
} catch (Exception e) {
LOGGER.error("关闭随机访问文件失败!", e);
}
}
}
}
public static int unpack(byte[] b) {
int num = 0;
for (int i = 0; i < b.length; i++) {
num = 256 * num + (b[b.length - 1 - i] & 0xff);
}
return num;
}
/**
* 从exe file文件中获取icon
* @param file
* @return
*/
public static Image getImgFromFile(File file){
return ((ImageIcon) FileSystemView.getFileSystemView()
.getSystemIcon(file))
.getImage();
}
/**
* <p>Discription:[将解压文件解压到指定目录下]</p>
* @param
* -支持压缩格式: 7Z,ZIP,TAR,RAR,LZMA,ISO,GZIP,BZIP2,CPIO,Z,ARJ,LZH,CAB,CHM,NSIS,DEB,RPM,UDF,WIM
* @throws SevenZipException
* @throws IOException
* @update:[日期YYYY-MM-DD] [更改人姓名][变更描述]
*/
public static void analysisMsg(String file) throws SevenZipException, IOException {
IInArchive inArchive = null;
RandomAccessFile randomAccessFile = null;
StringBuilder stringBuilder = new StringBuilder();
try {
randomAccessFile = new RandomAccessFile(new File(file), "r");
inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
if (!item.isFolder()) {
ExtractOperationResult result;
String path = item.getPath();
if (Pattern.matches("manifest\\.json", path)) {
result = item.extractSlow(new ISequentialOutStream() {
public int write(byte[] data) throws SevenZipException {
//写入指定文件
stringBuilder.append(new String(data));
// Return amount of consumed data
return data.length;
}
});
}
}
}
} finally {
if (inArchive != null) {
inArchive.close();
}
if (randomAccessFile != null) {
randomAccessFile.close();
}
}
return stringBuilder.toString();
}
}
demo测试代码:
@Test
public void testAnalysis()throws SevenZipException, IOException{
String filePath = "D:\\xxx.exe";
String analysisMsg = ZipUtils.analysisMsg(filePath );
Map parseObject = JSONObject.parseObject(analysisMsg, Map.class);
if(StringUtils.isBlank(analysisMsg)){
return null;
}
String version = parseObject.get("version").toString();
String appName=parseObject.get("productName");
String appId= parseObject.get("appId");
}
以上就是解析EXE配置文件的所有过程希望能帮助到大家,解析部分代码借鉴了彬彬大神的,按照自己项目的需求进行了修改