Java如何讀取.exe文件內的自定義配置文件

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章