java操作jar文件

前言

JAR(Java Archive File),表示Java档案文件,是一种压缩文件,与常见的ZIP压缩文件兼容。区别在于JAR文件中默认包含一个名为META-INF/MANIFEST.MF的清单文件,这个文件是生成JAR文件时由系统自动创建的。我们可以将代码打包成jar,加入到classpath中,JVM会自动解压jar包。

创建jar包

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Objects;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

public class Client {

  public static void main(String[] args) {
    compressFileToJar("D:/original_compute/testzip/test",
        "D:/original_compute/testzip/test.jar",
        "com.imooc.sourcecode.java.base.java5.autoboxing.test1.Client");
  }

  /**
   * 读取文件内容并压缩
   *
   * @param filePath 文件路径
   */
  private static void compressFileToJar(String filePath,
      String jarFilePath, String mainClass) {
    //创建清单文件,指定版本号和入口类
    Manifest manifest = new Manifest();
    Attributes attributes = manifest.getMainAttributes();
    attributes.put(Name.MANIFEST_VERSION, "1.0");
    attributes.put(Name.MAIN_CLASS, mainClass);
    try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFilePath), manifest)) {
      //递归的压缩文件夹和文件
      doCompress("", filePath, jos);
      //必须
      jos.finish();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private static void doCompress(String parentFilePath, String filePath, JarOutputStream jos) {
    File sourceFile = new File(filePath);
    if (!sourceFile.exists()) {
      return;
    }
    String jarEntryName = parentFilePath + "/" + sourceFile.getName();
    if (parentFilePath.isEmpty()) {
      jarEntryName = sourceFile.getName();
    }
    if (sourceFile.isDirectory()) {
      File[] childFiles = sourceFile.listFiles();
      if (Objects.isNull(childFiles)) {
        return;
      }
      for (File childFile : childFiles) {
        doCompress(jarEntryName, childFile.getAbsolutePath(), jos);
      }
    } else {
      int len = -1;
      byte[] buf = new byte[1024];
      jarEntryName = jarEntryName.substring(jarEntryName.indexOf("/") + 1);
      try (InputStream input = new BufferedInputStream(new FileInputStream(sourceFile))) {
        jos.putNextEntry(new JarEntry(jarEntryName));
        while ((len = input.read(buf)) != -1) {
          jos.write(buf, 0, len);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

}

将一个目录下的所有文件打包成jar包

可以直接通过java命令运行

java -jar ‪D:\original_compute\testzip\test.jar

解压jar包

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;

public class Client {

  public static void main(String[] args) {
    decompressFromJar("D:/original_compute/testzip/test.jar",
        "D:/original_compute/testzip/");
  }

  /**
   * 文件解压缩,支持文件和文件夹的解压
   *
   * @param jarFilePath 压缩包路径
   * @param destFilePath 解压路径
   */
  private static void decompressFromJar(String jarFilePath, String destFilePath) {
    File file = new File(jarFilePath);
    try (JarFile jarFile = new JarFile(file);
        JarInputStream jis = new JarInputStream(new FileInputStream(file))) {
      JarEntry jarEntry = null;
      while ((jarEntry = jis.getNextJarEntry()) != null) {
        String fileName = destFilePath + "/" + jarEntry.getName();
        File entryFile = new File(fileName);
        if (jarEntry.isDirectory()) {
          //创建文件夹
          entryFile.mkdir();
        } else {
          //创建文件之前必须保证父文件夹存在
          if (!entryFile.getParentFile().exists()) {
            entryFile.getParentFile().mkdirs();
          }
          //创建文件
          entryFile.createNewFile();
        }
        try (InputStream input = jarFile.getInputStream(jarEntry);
            OutputStream output = new FileOutputStream(entryFile)) {
          int len = -1;
          byte[] buf = new byte[1024];
          while ((len = input.read(buf)) != -1) {
            output.write(buf, 0, len);
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

  }
}

解压时会过滤掉清单文件

总结

JarInputStream和JarOutputStream都是ZipInputStream和ZipOutputStream的扩展类,不了解ZipInputStream的可以看 java操作zip文件

posted @ 2020-12-28 20:26  strongmore  阅读(490)  评论(0编辑  收藏  举报