前言
因為之前開發過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配置檔案的所有過程希望能幫助到大家,解析部分代碼借鑒了彬彬大神的,按照自己項目的需求進行了修改