前言
因爲之前開發過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();
}
/**
* <p>Description: [提後文件後回調方法]</p>
* @version $Revision$
*/
private class ExtractCallback implements IArchiveExtractCallback
{
private final IInArchive inArchive;
private final String extractPath;
public ExtractCallback(IInArchive inArchive, String extractPath)
{
this.inArchive = inArchive;
if (!extractPath.endsWith("/") && !extractPath.endsWith("\\"))
{
extractPath += File.separator;
}
this.extractPath = extractPath;
}
@Override
public ISequentialOutStream getStream(final int index, ExtractAskMode extractAskMode) throws SevenZipException
{
return new ISequentialOutStream(){
@Override
public int write(byte[] data) throws SevenZipException
{
String filePath = inArchive.getStringProperty(index, PropID.PATH);
FileOutputStream fos = null;
try
{
File path = new File(extractPath + filePath);
if (!path.getParentFile().exists())
{
path.getParentFile().mkdirs();
}
if (!path.exists())
{
path.createNewFile();
}
fos = new FileOutputStream(path, true);
fos.write(data);
}
catch (IOException e)
{
LOGGER.error(null, "IOException while extracting " + filePath);
}
finally
{
try
{
if (fos != null)
{
fos.flush();
fos.close();
}
}
catch (IOException e)
{
LOGGER.error(null, "Could not close FileOutputStream", e);
}
}
return data.length;
}
};
}
@Override
public void setCompleted(long arg0) throws SevenZipException
{
}
@Override
public void setTotal(long arg0) throws SevenZipException
{
}
@Override
public void prepareOperation(ExtractAskMode arg0) throws SevenZipException
{
}
@Override
public void setOperationResult(ExtractOperationResult arg0) throws SevenZipException
{
}
}
}
demo測試代碼:
@Test
public void testAnalysis()throws SevenZipException, IOException{
String filePath = "D:\\xxx.e";
analysisMsg(filePath);
}
以上就是解析EXE配置文件的所有過程希望能幫助到大家,解析部分代碼借鑑了彬彬大神的,按照自己項目的需求進行了修改