jar中读取文件

Java   技巧   49:如何从   JAR   和   zip   档案文件中提取   Java   资源  
  您是刚开始接触   JAR   文件吗?这个新类可帮您解决问题!  
   
  作者:John   D.   Mitchell   和   Arthur   Choi  
   
  摘要  
  将一类   Java   资源打包在一个   Java   ARchive   (JAR)   文件中是缩短下载时间、增强安全性和增强可管理性的极好方法。这篇技巧说明如何很容易地从   JAR   文件中提取资源以供您自己使用。    
  多数   Java   程序员都非常清楚使用   JAR   文件将组成   Java   解决方案的各种资源(即   .class   文件、声音和图像)打包的优点。(如果您不熟悉   JAR   文件,请参阅后文的参考资源部分。)刚开始使用   JAR   文件的人常问的一个问题是:“如何从   JAR   文件中提取图像呢?”本文将回答这个问题,并会提供一个类,这个类使从   JAR   文件中提取任何资源变得非常简单!    
  加载   GIF   图像  
  假定我们有一个   JAR   文件,其中包含我们的应用程序要使用的一组   .gif   图像。下面就是使用   JarResources   访问   JAR   文件中的图像文件的方法:    
   
          JarResources   jar   =   new   JarResources   ("Images.jar");  
          Image   logo   =  
    Toolkit.getDefaultToolkit().createImage   (jar.getResource   ("logo.gif");  
   
   
  这段代码说明我们可以创建一个   JarResources   对象,并将其初始化为包含我们要使用的资源的   JAR   文件   --   Images.jar。随后我们使用   JarResources   的   getResource()   方法将来自   logo.gif   文件的原始数据提供给   AWT   Toolkit   的   createImage()   方法。    
   
  命名说明  
  JarResource   是一个非常简单的示例,它说明了如何使用   Java   1.1   所提供的各种功能来处理   JAR   和   zip   档案文件。    
   
  关于命名的简要说明。Java   中的归档支持实际上是以流行的   zip   归档格式为起点的(请参阅   "Java   Tip   21:   Use   archive   files   to   speed   up   applet   loading")。因此,在最初实现处理档案文件的   Java   支持时,所有类文件以及诸如此类的东西并未放在   java.util.zip   包中;这些类通常以   "Zip"   开头。但在转向   Java   1.1   时,功能已发生了变化,档案文件的名称也更具有   Java   特征。因此,现在我们称之为   JAR   文件的文件基本上是   zip   文件。    
   
  工作方式  
  JarResources   类的重要数据域用来跟踪和存储指定   JAR   文件的内容:    
   
  public   final   class   JarResources   {  
   
        public   boolean   debugOn=false;  
   
        private   Hashtable   htSizes=new   Hashtable();    
        private   Hashtable   htJarContents=new   Hashtable();  
   
        private   String   jarFileName;  
   
   
  这样,该类的实例化设置   JAR   文件的名称,然后转到   init()   方法完成全部实际工作。    
   
        public   JarResources(String   jarFileName)   {  
              this.jarFileName=jarFileName;  
              init();  
        }  
   
   
  现在,init()   方法只将指定   JAR   文件的整个内容加载到一个   hashtable(通过资源名访问)中。    
   
  这是一个相当有用的方法,下面我们对它作进一步的分析。ZipFile   类为我们提供了对   JAR/zip   档案头信息的基本访问方法。这类似于文件系统中的目录信息。下面我们列出   ZipFile   中的所有条目,并用档案中每个资源的大小添充   htSizes   hashtable:    
   
        private   void   init()   {  
              try   {  
                      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();  
   
   
  接下来,我们使用   ZipInputStream   类访问档案。ZipInputStream   类完成了全部魔术,允许我们单独读取档案中的每个资源。我们从档案中读取组成每个资源的精确字节数,并将其存储在   htJarContents   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   表示大小未知。  
                            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;  
                            }  
                            //   添加到内部资源   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();  
                }  
        }  
   
   
  请注意,用来标识每个资源的名称是档案中资源的限定路径名,例如,不是包中的类名   --   即   java.util.zip   包中的   ZipEntry   类将被命名为   "java/util/zip/ZipEntry",而不是   "java.util.zip.ZipEntry"。    
   
  代码的最后一个重要部分是简单的测试驱动程序。该测试驱动程序是一个简单的应用程序,它接收   JAR/zip   档案名和资源名。它试图发现档案中的资源文件,然后将成功或失败的消息报告出来:    
   
        public   static   void   main(String[]   args)   throws   IOException   {  
                if   (args.length!=2)   {  
                      System.err.println(  
                            "usage:   java   JarResources   "  
                            );  
                      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+").");  
                }  
        }  
   
  }   //   JarResources   类结束。  
   
   
  您已了解了这个类。一个易于使用的类,它隐藏了使用打包在   JAR   文件中的资源的全部棘手问题。    
   
  练习  
  现在您对从档案文件中提取资源已有了一定的认识,下面是可用来修改和扩展   JarResources   类的一些说明:    
   
   
  不在构造期间一次性加载全部内容,而要延迟加载。对于大型   JAR   文件,构造期间可能没有足够的内存加载全部文件。    
   
  不只是提供类似   getResource()   这样的一般读方法,我们还可提供资源特定的读方法   --   例如,用来返回   Java   Image   对象的   getImage()   方法,用来返回   Java   Class   对象的   getClass()   方法(在自定义的类加载程序的协助下),等等。如果   JAR   文件足够小,则我们可以根据它们的扩展名(.gif、.class   等等)预先构建全部资源。    
   
  某些方法应该提供关于给定   JAR   文件本身(基本上是   ZipFile   的包装)的信息,包括:Jar/zip   的条目数;返回全部资源名的   Enumerator;返回特定条目长度(和其他属性)的读方法;允许编制索引的读方法,这仅仅是举几个例子。    
   
  可对   JarResources   进行扩展,以供   applet   使用。通过利用   applet   参数和   URLConnection   类,就可以从网络上下载   JAR   内容,而不是将档案作为本地文件打开。此外,我们还可将该类扩展为一个自定义的   Java   内容处理程序。    
  小结  
  如果您曾经渴望知道如何从   JAR   文件中提取图像,那么您现在已学到了一种方法。有了本技巧提供的这个新类,您就不仅可以用   JAR   文件处理图像,而且可以将提取魔术用于   JAR   文件中的任何资源。    
   
  作者简介    
  Arthur   Choi   目前是   IBM   的一位顾问程序员。他曾先后在几个公司任职,包括   SamSung   Network   Laboratory   和   MITRE。他参与过的项目包括客户机/服务器系统、分布式对象计算和网络管理。他在各种操作系统环境下用过多种语言。他于   1981   年开始用   FORTRAN   IV   和   COBOL   进行编程。后来他转向   C   和   C++,最近两年他一直在用   Java   工作。他最感兴趣的   Java   应用是广域网中的数据仓库和因特网上的并行处理和分布式处理(使用基于代理的编程)。Reach   Arthur   的电子邮件地址为   arthur.choi@javaworld.com。    
  John   Mitchell,先后做过雇员、咨询人员,现在是自己公司的老板,过去十年他所投资的领域包括前沿计算机软件的开发、对其他开发人员提供建议和培训。他 的咨询范围包括   Java   技术、编译器、解释器、基于   Web   应用和因特网商务等。John   是   Making   Sense   of   Java:   A   Guide   for   Managers   and   the   Rest   of   Us   一书的作者之一,并在编程杂志上发表了许多文章。除了为   JavaWorld   撰写   Java   Tips   专栏之外,他还主持着   comp.lang.tcl.announce   和   comp.binaries.geos   新闻组。Reach   John   的电子邮件地址为   john.mitchell@javaworld.com。    
     
   
   
  参考资源    
   
  这是类文件   JarResources.java    
  JarResources.java    
  JARs    
  http://www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html    
  有关   Java   的归档支持的详细信息,请参阅   "Java   Tip   21:   Use   archive   files   to   speed   up   applet   loading"    
  http://www.javaworld.com/javatips/jw-javatip21.html    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值