快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

怎样制作自解压的JAR文件

这是一篇描述怎样制作自解压jar文件的文章,作者通过自己编写的一个自解压程序,并把这个自解压程序以及一个manifest文件一起加入原始的jar文件中,就制作出一个可以在各种支持java的平台上运行的自解压的jar 文件。

自解压文件
我们先来了解一下自解压文件,在window下可以用自解压制作工具如winzip self-Extractor来制作自解压文件,这些工具会把一个zip文件与解压程序打包在一起而产生一个新的可执行文件。然后只要运行这个可执行文件,就可以把zip文件中的内容解开。那为什么要创建自解压jar文件呢,创建成自解压zip文件不就好了?我们应该注重到自解压jar文件可以在任意支持java的平台上解开并执行,例如,可以在linux下执行。创建jar自解压文件很简朴,只需要一个特别的JAR manifest文件、一个基于java的解压程序(这个程序是原作者写的)、包含基本文件的jar 或者zip文件以及任何jsdk的jar应用程序

manifest文件
要生成可执行jar文件,需要在META-INF 目录下的manifest文件,文件名为:MANIFEST.MF ,但在我们这里我们只需要在文件中指定在这个基于java 的解压程序中包含main()的类的名称:Main-Class: ZipSelfExtractor

我们已经把一个叫做jarmanifest的文件加入到这个技巧的源程序包中。

解压程序
你可以用各种方式来实现这个解压程序,在我们这里使用了一个简朴直接的办法。首先,解压程序判定这个自解压jar文件的名称,有了这个文件名,解压程序使用解压标准,把文件解开。详细的可以查看在源码包中的ZipSelfExtractor.java文件。

值得一提的是这里用了一个很巧妙的办法获取jar文件的文件名,虽然在命令行中出现的这个文件的名字,但它并没有作为参数传入类的main()中,因此,这里使用了以下的代码来获取文件名:

private String getJarFileName ()
{
myClassName = this.getClass().getName() + ".class";
URL urlJar =
this.getClass().getClassLoader().getSystemResource(myClassName);
String urlStr = urlJar.toString();
int from = "jar:file:".length();
int to = urlStr.indexOf("!/");
return urlStr.substring(from, to);
}

请注重:getSystemResource() 中使用了myClassName而不是ZipSelfExtractor.class作参数,这使得我们可以更改加压程序的名字而不需要修改代码。

接下来,我们来分析获得这个jar文件的名字。首先,可以获取指向包含正在运行类的文件,urlStr = urlJar.toString();有了这个url,把jar文件名去掉,剩下的就是我们想要的,下面是这个url的格式:
jar:file:/home/test/zipper.jar!/ZipSelfExtractor.class

有了文件名,就可以开始解压,具体的解压算法请大家自己看源码。

为了可以更方便实用,程序使用了图形界面,程序中使用了JFileChooser类可以选择要解压的目标目录。

最后程序还确保不把这两个文件:manifest文件和extractor´s .class(在我们这里是ZipSelfExtractor.class)文件也解出来,程序是用来解开原始的jar的内容,而这两个文件并属于jar原始内容。

打包jar文件
有了manifest文件与解压程序,我们就可以创建自解压jar文件了,以下是一个例子:
1.创建一个zip文件Myzip.zip
2.下载zipper.jar
3.把文件解到当前目录,预备制作自解压jar文件
java -jar zipper.jar
4.把zipper.class拷贝成 ZipSelfExtractor.class
5.把 myzip.zip 重命名为 myzip.jar
6.把myzip.jar中的内容替换为jarmanifest和ZipSelfExtractor.class这两个文件
jar uvfm myzip.jar jarmanifest ZipSelfExtractor.class
7.执行java -jar myzip.jar就可以看到效果了,试试看

后记
一个自解压的jar文件能够很好的跨平台使用,自解压jar文件创建简朴,只需要有jre1.2或或者更新的版本就可以实现了。

附自解压程序的源代码:

/* ZipSelfExtractor.java */
/* Author: Z.S. Jin
Updates: John D. Mitchell */

import java.io.*;
import java.net.*;
import javax.swing.*;
import java.util.zip.*;
import java.util.*;
import java.text.*;

public class ZipSelfExtractor extends JFrame
{
private String myClassName;
static String MANIFEST = "META-INF/MANIFEST.MF";

public static void main(String[] args)
{
ZipSelfExtractor zse = new ZipSelfExtractor();
String jarFileName = zse.getJarFileName();
zse.extract(jarFileName);
System.exit(0);
}

ZipSelfExtractor()
{
}

private String getJarFileName()
{
myClassName = this.getClass().getName() + ".class";
URL urlJar = this.getClass().getClassLoader().getSystemResource(myClassName);
String urlStr = urlJar.toString();
int from = "jar:file:".length();
int to = urlStr.indexOf("!/");
return urlStr.substring(from, to);
}

public void extract(String zipfile)
{
File currentArchive = new File(zipfile);

JFileChooser fc = new JFileChooser();

fc.setCurrentDirectory(new File("."));
fc.setDialogType(JFileChooser.OPEN_DIALOG);
fc.setDialogTitle("Select destination directory for extracting " +
currentArchive.getName());
fc.setMultiSelectionEnabled(false);

fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

if (fc.showDialog(ZipSelfExtractor.this, "Select")
!= JFileChooser.APPROVE_OPTION)
{
return; //only when user select valid dir, it can return approve_option
}

File outputDir = fc.getSelectedFile();

byte[] buf = new byte[1024];
SimpleDateFormat formatter = new SimpleDateFormat ("MM/dd/yyyy hh:mma",Locale.getDefault());

ProgressMonitor pm = null;

boolean overwrite = false;

ZipFile zf = null;
FileOutputStream out = null;
InputStream in = null;

try
{
zf = new ZipFile(currentArchive);

int size = zf.size();
int extracted = 0;
pm = new ProgressMonitor(getParent(), "Extracting files...", "starting", 0, size-4);
pm.setMillisToDecideToPopup(0);
pm.setMillisToPopup(0);

Enumeration entries = zf.entries();

for (int i=0; i<size; i++)
{
ZipEntry entry = (ZipEntry) entries.nextElement();
if(entry.isDirectory())
continue;

String pathname = entry.getName();
if(myClassName.equals(pathname) || MANIFEST.equals(pathname.toUpperCase()))
continue;

extracted ++;
pm.setProgress(i);
pm.setNote(pathname);
if(pm.isCanceled())
return;

in = zf.getInputStream(entry);

File outFile = new File(outputDir, pathname);
Date archiveTime = new Date(entry.getTime());

if(overwrite==false)
{
if(outFile.exists())
{
Object[] options = {"Yes", "Yes To All", "No"};
Date existTime = new Date(outFile.lastModified());
Long archiveLen = new Long(entry.getSize());

String msg = "File name conflict: "
+ "There is already a file with "
+ "that name on the disk! "
+ " File name: " + outFile.getName()
+ " Existing file: "
+ formatter.format(existTime) + ", "
+ outFile.length() + "Bytes"
+ " File in archive:"
+ formatter.format(archiveTime) + ", "
+ archiveLen + "Bytes"
+" Would you like to overwrite the file?";

int result = JOptionPane.showOptionDialog(ZipSelfExtractor.this,
msg, "Warning", JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE, null, options,options[0]);

if(result == 2) // No
{
continue;
}
else if( result == 1) //YesToAll
{
overwrite = true;
}
}
}

File parent = new File(outFile.getParent());
if (parent != null && !parent.exists())
{
parent.mkdirs();
}

out = new FileOutputStream(outFile);

while (true)
{
int nRead = in.read(buf, 0, buf.length);
if (nRead <= 0)
break;
out.write(buf, 0, nRead);
}

out.close();
outFile.setLastModified(archiveTime.getTime());
}

pm.close();
zf.close();
getToolkit().beep();

JOptionPane.showMessageDialog
(ZipSelfExtractor.this,
"Extracted " + extracted +
" file" + ((extracted > 1) ? "s": "") +
" from the " +
zipfile + " archive into the " +
outputDir.getPath() +
" directory.",
"Zip Self Extractor",
JOptionPane.INFORMATION_MESSAGE);

}
catch (Exception e)
{
System.out.println(e);
if(zf!=null) { try { zf.close(); } catch(IOException ioe) {;} }
if(out!=null) { try {out.close();} catch(IOException ioe) {;} }
if(in!=null) { try { in.close(); } catch(IOException ioe) {;} }
}
}
}
返回类别: 教程
上一教程: 改变JSP的文件后缀
下一教程: TOMCAT SERVER 原理

您可以阅读与"怎样制作自解压的JAR文件"相关的教程:
· 制作可以执行的 JAR 文件包及 JAR 命令详解
· 制作可执行的JAR文件包及JAR命令详解
· &quot;package中的javac,java用法&quot; &amp;&amp; &quot;制作可执行jar文件&quot;
· JAVA 中 JAR 文件的编写和应用
· 用JAVA制作网络文件下载系统
    微笑服务 优质保证 索取样品