Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 446|回复: 0

[Java基础知识]从JAR和zip档案文件中提取Java 资源

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-2 03:12:09 | 显示全部楼层 |阅读模式
    如何从 jar 和 zip 档案文件中提取 java 资源
    作者:john d. mitchell 和 arthur choi
      
    [blockquote]
    摘要
    将一类 java 资源打包在一个 java arcHive (jar) 文件中是缩短下载时间、增强安全性和增强可管理性的极好方法。这篇技巧说明如何很容易地从 jar 文件中提取资源以供您自己使用。

    [/blockquote]  
      多数 java 程序员都非常清楚使用 jar 文件将组成 java 解决方案的各种资源(即 .class 文件、声音和图像)打包的优点。刚开始使用 jar 文件的人常问的一个问题是:“如何从 jar 文件中提取图像呢?”本文将回答这个问题,并会提供一个类,这个类使从 jar 文件中提取任何资源变得非常简单!
      加载 gif 图像
        假定我们有一个 jar 文件,其中包含我们的应用程序要使用的一组 .gif 图像。下面就是使用 JarResources 访问 jar 文件中的图像文件的方法:
    1.     JarResources JR=new JarResources("GifBundle.jar");
    2.      Image logo=Toolkit.getDefaultToolkit().createImage(JR.getResources("logo.gif"));
    复制代码
         这段代码说明我们可以创建一个
    1. JarResources
    复制代码
    对象,并将其初始化为包含我们要使用的资源的 jar 文件 --
    1. images.jar
    复制代码
    。随后我们使用
    1. JarResources
    复制代码
    1. getResource()
    复制代码
    方法将来自 logo.gif 文件的原始数据提供给 awt Toolkit 的
    1. createImage()
    复制代码
    方法。
    命名说明
    JarResource 是一个非常简单的示例,它说明了如何使用 java 所提供的各种功能来处理 jar 和 zip 档案文件。

      工作方式
    1. JarReources
    复制代码
    类的重要数据域用来跟踪和存储指定 jar 文件的内容:
    1. public final class JarResources {
    2.     public boolean debugon=false;
    3.     private Hashtable htsizes=new Hashtable();
    4.     private Hashtable htjarcontents=new Hashtable();
    5.     private String jarfilename;
    复制代码
    这样,该类的实例化设置 jar 文件的名称,然后转到
    1. init()
    复制代码
    方法完成全部实际工作。
    1.    public JarResources(String jarfilename) {
    2.        this.jarfilename=jarfilename;
    3.        init();
    4.     }
    复制代码
    现在,
    1. init()
    复制代码
    方法只将指定 jar 文件的整个内容加载到一个 hashtable(通过资源名访问)中。

           这是一个相当有用的方法,下面我们对它作进一步的分析。
    1. ZipFile
    复制代码
    类为我们提供了对 jar/zip 档案头信息的基本访问方法。这类似于文件系统中的目录信息。下面我们列出
    1. ZipFile
    复制代码
    中的所有条目,并用档案中每个资源的大小添充 htsizes hashtable:
      private void init() {
          try {
              // extracts just sizes only.
              ZipFile zf=new ZipFile(jarFileName);
              Enumeration e=zf.entries();
              while (e.hasMoreElements()) {
                  ZipEntry ze=(ZipEntry)e.nextElement();
                  if (debugOn) {
                     System.out.println(dumpZipEntry(ze));
                  }
                  htSizes.put(ze.getName(),new Integer((int)ze.getSize()));
              }
              zf.close();[/code] 接下来,我们使用
    1. ZipInputStream
    复制代码
    类访问档案。
    1. ZipInputStream
    复制代码
    类完成了全部魔术,允许我们单独读取档案中的每个资源。我们从档案中读取组成每个资源的精确字节数,并将其存储在 htjarcontents hashtable 中,您可以通过资源名访问这些数据:
    1.      
    复制代码
              // extract resources and put them into the hashtable.
              FileInputStream fis=new FileInputStream(jarFileName);
              BufferedInputStream bis=new BufferedInputStream(fis);
              ZipInputStream zis=new ZipInputStream(bis);
              ZipEntry ze=null;
              while ((ze=zis.getNextEntry())!=null) {
                 if (ze.isDirectory()) {
                    continue;////啊哟!没有处理子目录中的资源啊
                 }
                 if (debugOn) {
                    System.out.println(
                       "ze.getName()="+ze.getName()+","+"getSize()="+ze.getSize()
                       );
                 }
                 int size=(int)ze.getSize();
                 // -1 means unknown size.
                 if (size==-1) {
                    size=((Integer)htSizes.get(ze.getName())).intValue();
                 }
                 byte[] b=new byte[(int)size];
                 int rb=0;
                 int chunk=0;
                 while (((int)size - rb) > 0) {
                     chunk=zis.read(b,rb,(int)size - rb);
                     if (chunk==-1) {
                        break;
                     }
                     rb+=chunk;
                 }
                 // add to internal resource hashtable
                 htJarContents.put(ze.getName(),b);
                 if (debugOn) {
                    System.out.println(
                       ze.getName()+"  rb="+rb+
                       ",size="+size+
                       ",csize="+ze.getCompressedSize()
                       );
                 }
              }
           } catch (NullPointerException e) {
              System.out.println("done.");
           } catch (FileNotFoundException e) {
              e.printStackTrace();
           } catch (IOException e) {
              e.printStackTrace();
           }
       }
    [/code] 请注意,用来标识每个资源的名称是档案中资源的限定路径名,例如,不是包中的类名 -- 即 java.util.zip 包中的
    1. ZipEntry
    复制代码
    类将被命名为 "java/util/zip/ZipEntry",而不是 "java.util.zip.ZipEntry"。

    其它方法:    /**
        * Dumps a zip entry into a string.
        * @param ze a ZipEntry
        */
       private String dumpZipEntry(ZipEntry ze) {
           StringBuffer sb=new StringBuffer();
           if (ze.isDirectory()) {
              sb.append("d ");
           } else {
              sb.append("f ");
           }
           if (ze.getMethod()==ZipEntry.STORED) {
              sb.append("stored   ");
           } else {
              sb.append("defalted ");
           }
           sb.append(ze.getName());
           sb.append("        ");
           sb.append(""+ze.getSize());
           if (ze.getMethod()==ZipEntry.DEFLATED) {
              sb.append("/"+ze.getCompressedSize());
           }
           return (sb.toString());
       }

        /**
        * Extracts a jar resource as a blob.
        * @param name a resource name.
        */
       public byte[] getResource(String name) {
          return (byte[])htJarContents.get(name);
       }
          [/code] 代码的最后一个重要部分是简单的测试驱动程序。该测试驱动程序是一个简单的应用程序,它接收 jar/zip 档案名和资源名。它试图发现档案中的资源文件,然后将成功或失败的消息报告出来: public static void main(String[] args) throws IOException {
           if (args.length!=2) {
              System.err.println(
                 "usage: java JarResources < jar file name> < resource name>"
                 );
              System.exit(1);
           }
           JarResources jr=new JarResources(args[0]);
           byte[] buff=jr.getResource(args[1]);
           if (buff==null) {
              System.out.println("Could not find "+args[1]+".");
           } else {
              System.out.println("Found "+args[1]+ " (length="+buff.length+").");
           }
       }
    }        // End of JarResources class.
    [/code] 您已了解了这个类。一个易于使用的类,它隐藏了使用打包在 jar 文件中的资源的全部棘手问题。
      练习
    现在您对从档案文件中提取资源已有了一定的认识,下面是可用来修改和扩展
    1. JarResources
    复制代码
    类的一些说明:


    不在构造期间一次性加载全部内容,而要延迟加载。对于大型 jar 文件,构造期间可能没有足够的内存加载全部文件。
      
    不只是提供类似
    1. getResource()
    复制代码
    这样的一般读方法,我们还可提供资源特定的读方法 -- 例如,用来返回 java
    1. image
    复制代码
    对象的
    1. getImage()
    复制代码
    方法,用来返回 java
    1. class
    复制代码
    对象的
    1. getclass()
    复制代码
    方法(在自定义的类加载程序的协助下),等等。如果 jar 文件足够小,则我们可以根据它们的扩展名(.gif、.class 等等)预先构建全部资源。

    某些方法应该提供关于给定 jar 文件本身(基本上是
    1. zipfile
    复制代码
    的包装)的信息,包括:jar/zip 的条目数;返回全部资源名的 enumerator;返回特定条目长度(和其他属性)的读方法;允许编制索引的读方法,这仅仅是举几个例子。

    可对
    1. JarResources
    复制代码
    进行扩展,以供 applet 使用。通过利用 applet 参数和
    1. urlconnection
    复制代码
    类,就可以从网络上下载 jar 内容,而不是将档案作为本地文件打开。此外,我们还可将该类扩展为一个自定义的 java 内容处理程序。  
    小结
    如果您曾经渴望知道如何从 jar 文件中提取图像,那么您现在已学到了一种方法。有了本技巧提供的这个新类,您就不仅可以用 jar 文件处理图像,而且可以将提取魔术用于 jar 文件中的任何资源。  
       

      
      
       
       

         
       

         
       
      
      

    源码下载:http://file.javaxxz.com/2014/10/2/031208719.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-27 04:27 , Processed in 0.422199 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表