{"id":176,"date":"2021-01-19T21:54:58","date_gmt":"2021-01-19T21:54:58","guid":{"rendered":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/?page_id=176"},"modified":"2021-01-19T22:15:18","modified_gmt":"2021-01-19T22:15:18","slug":"zip-jar-files","status":"publish","type":"page","link":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/","title":{"rendered":"ZIP &#038; JAR Files"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a6d4a1620030\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a6d4a1620030\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/#ZIP_File_Streams\" >ZIP File Streams<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/#Classes_ZipInputStream_ZipEntry\" >Classes ZipInputStream &amp; ZipEntry<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/#Using_the_ZipInputStream_Class\" >Using the ZipInputStream Class<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/#Class_ZipFile\" >Class ZipFile<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/#Using_the_ZipFile_Class\" >Using the&nbsp;ZipFile&nbsp;Class<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/#JAR_File_Streams\" >JAR File Streams<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/i-o-files-streams\/zip-jar-files\/#Classes_JarFile_JarEntry\" >Classes JarFile &amp; JarEntry<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n<p class=\"wp-block-paragraph\"><strong>ZIP<\/strong> files and <strong>JAR<\/strong> (Java Archive) files are very useful, and are heavily used in Java.&nbsp;<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>JAR files are&nbsp;archive files&nbsp;that include a Java-specific&nbsp;<strong>manifest file<\/strong>. A manifest file is a&nbsp;metadata&nbsp;file contained within a JAR.&nbsp;It defines extension and package-related data.<\/p><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">For example, in JDK 1.5, the code for the Java class library may be found in a ZIP file&nbsp;<strong>src.zip<\/strong>&nbsp;(in the top level directory for the JDK installation).&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When loading a Java program (application or applet), it is more efficient to load from a ZIP or JAR file &#8212; only one file needs to be opened and read, rather than many different&nbsp;<code><strong>.class<\/strong><\/code>&nbsp;files. When downloading a set of files from the web, especially, using a ZIP or JAR file can have a considerable impact on performance.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So it stands to reason that Java contains a number of classes that are used to read and write ZIP and JAR files.&nbsp; Here&#8217;s how you can do this yourself&#8230;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ZIP_File_Streams\"><\/span>ZIP File Streams<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the hierarchy of classes that are used to process Zip files:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">(Package&nbsp;<code><strong>java.util.zip<\/strong><\/code>)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Object<strong>\n    Adler32\n    CRC32\n    Deflater\n    Inflater\n    ZipEntry\n    ZipFile<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>CheckSum (interface)<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">Object\n    InputStream\n        FilterInputStream<strong>\n            CheckedInputStream\n            InflaterInputStream\n                GZIPInputStream\n                ZipInputStream\n    <\/strong>OutputStream\n        FilterOutputStream<strong>\n            CheckedOutputStream\n            DeflaterOutputStream\n                GZIPOutputStream\n                ZipOutputStream<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">Object\n    Throwable\n        Exception<strong>\n            DataFormatException\n            <\/strong>IOException<strong>\n                ZipException<\/strong><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Classes_ZipInputStream_ZipEntry\"><\/span>Classes ZipInputStream &amp; ZipEntry<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using the ZIP file streams is relatively simple. Each file within the ZIP file has a header with information including the name of the file and the compression method that was used.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Using_the_ZipInputStream_Class\"><\/span>Using the <strong>ZipInputStream<\/strong> Class<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You use a&nbsp;<strong>ZipInputStream<\/strong>&nbsp;to read a ZIP file.&nbsp; Each file within the ZIP file is represented by a&nbsp;<strong>ZipEntry<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an example of how to read a ZIP file using <strong>ZipInputStream<\/strong> and <strong>ZipEntry<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage inputOutput;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.InputStreamReader;\nimport java.io.IOException;\n\nimport java.util.zip.ZipInputStream;\nimport java.util.zip.ZipEntry;\nimport javax.swing.JComboBox;\nimport javax.swing.JFileChooser;\nimport javax.swing.JFrame;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JMenuItem;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextArea;\nimport javax.swing.UIManager;\n\n\/**\n *   Class to open a ZIP file, and display a list of files\n *   stored within it.\n *   When the user selects a ZIP file, the contents of the\n *   file (assumed to be text) are displayed in the text\n *   area.\n *\n *   @author Bryan J. Higgs, 19 September, 1999\n *\/\npublic class ReadZipFile extends JFrame\n{\n  \/**\n   *   Main entry point.\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    try\n    {\n      \/\/ Set the system look and feel\n      UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );\n    } \n    catch (Exception ex)\n    {\n      \/\/ Ignore\n    } \n    \n    ReadZipFile frame = new ReadZipFile();\n    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n    frame.setVisible(true);\n  }\n  \n  \/**\n   *   Constructor.\n   *\/\n  public ReadZipFile()\n  {\n    setTitle(&quot;ZIP File Reader&quot;);\n      \n    \/\/ Set up frame menus\n    JMenuBar menuBar = new JMenuBar();\n    setJMenuBar(menuBar);\n    \n    JMenu fileMenu = new JMenu(&quot;File&quot;);\n    menuBar.add(fileMenu);\n    \n    JMenuItem openItem = new JMenuItem(&quot;Open&quot;);\n    fileMenu.add(openItem);\n    openItem.addActionListener( new OpenAction() );\n    \n    JMenuItem exitItem = new JMenuItem(&quot;Exit&quot;);\n    fileMenu.add(exitItem);\n    exitItem.addActionListener( new ActionListener()\n      {\n        public void actionPerformed(ActionEvent event)\n        {\n          System.exit(0);\n        }\n      }\n    );\n    \n    \/\/ Set the size of the combo box, and\n    \/\/ hook it up to its actions\n    m_fileList.setEditable(false);\n    m_fileList.addItem(&quot;Use File-&gt;Open to select ZIP file&quot;);\n    m_fileList.addActionListener( new ActionListener()\n    {\n      public void actionPerformed(ActionEvent event)\n      {\n        String item = (String) m_fileList.getSelectedItem();\n        if (item != null)\n          loadZipFile(item);\n      }\n    }\n    );\n    m_fileText.setEditable(false);\n    m_fileText.setBackground(Color.WHITE);\n    \n    add(m_fileList, BorderLayout.SOUTH);\n    add(new JScrollPane(m_fileText), BorderLayout.CENTER);\n    pack();\n  }\n  \n  \/**\n   *   Inner class to handle open file events.\n   *\/\n  private class OpenAction implements ActionListener\n  {\n    public void actionPerformed(ActionEvent event)\n    {\n      JFileChooser chooser = new JFileChooser();\n      chooser.setCurrentDirectory( new File(&quot;.&quot;) );\n      TypeFileFilter filter = new TypeFileFilter(&quot;.zip&quot;);\n      filter.setDescription(&quot;ZIP files&quot;);\n      chooser.setFileFilter(filter);\n      int ret = chooser.showOpenDialog(ReadZipFile.this);\n      if (ret == JFileChooser.APPROVE_OPTION)\n      {\n        m_zipFileName = chooser.getSelectedFile().getPath();\n        scanZipFile(m_zipFileName);\n      }\n    }\n  }\n  \n  \/**\n   * Scans the ZIP file and populates the combo box.\n   *\/\n  public void scanZipFile(String zipFileName)\n  {\n    \/\/ Clean out the list, in case it&#039;s already in use.\n    m_fileList.removeAllItems();\n    ZipInputStream zin = null;\n    ZipEntry entry = null;\n    try\n    {\n      zin = new ZipInputStream( new FileInputStream(zipFileName) );\n      while ( (entry = zin.getNextEntry()) != null )\n      {\n        m_fileList.addItem(entry.getName());\n        zin.closeEntry();\n      }\n      m_zipFileName = zipFileName;\n    }\n    catch (IOException ioe)\n    {\n      ioe.printStackTrace();\n    }\n    finally\n    {\n      try\n      {\n        zin.close();\n      } \n      catch (IOException ex)\n      {\n        \/\/ Ignore\n      }\n    }\n  }\n  \n  \/**\n   *   Displays the files within the ZIP file,\n   *   in the List component.\n   *\/\n  private void loadZipFile(String name)\n  {\n    ZipInputStream zin = null;\n    ZipEntry entry = null;\n    try\n    {\n      \/\/ Open the Zip file stream\n      zin = new ZipInputStream( new FileInputStream(m_zipFileName) );\n      \/\/ Scan through the entries until we find the one that matches\n      while ( (entry = zin.getNextEntry()) != null)\n      {\n        \/\/ Does the name match?\n        if (entry.getName().equals(name))\n        {\n          \/\/ Read the entry into the text area\n          BufferedReader in = new BufferedReader( new InputStreamReader(zin) );\n          String line;\n          while ( (line = in.readLine()) != null)\n          {\n            m_fileText.append(line);\n            m_fileText.append(&quot;\\n&quot;);\n          }\n          \/\/ Be sure to show the start of the file, after loading.\n          m_fileText.setCaretPosition(0);\n        }\n        zin.closeEntry();\n      }\n    }\n    catch (IOException ioe)\n    {\n      ioe.printStackTrace();\n    }\n    finally\n    {\n      try\n      {\n        if (zin != null)\n          zin.close();\n      } \n      catch (IOException ex)\n      {\n        \/\/ Ignore\n      }\n    }\n  }\n  \n  \/\/\/\/\/\/\/ Private data \/\/\/\/\/\/\/\/\/\n  \n  private JComboBox m_fileList = new JComboBox();\n  private JTextArea m_fileText = new JTextArea(30, 80);\n  private String    m_zipFileName;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The above class uses a <strong>FileFilter<\/strong> for the <strong>FileChooser<\/strong> dialog:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage inputOutput;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport javax.swing.filechooser.FileFilter;\n\n\/**\n * Class to provide a file filter based on one or more\n * extensions (file types)\n *\n *\/\npublic class TypeFileFilter extends FileFilter\n{\n  \/**\n   * Creates a new instance of TypeFileFilter\n   * for a single file type\n   *\/\n  public TypeFileFilter(String type)\n  {\n    addType(type);\n  }\n\n  \/**\n   * Adds a new file type to the filter\n   *\/\n  public void addType(String type)\n  {\n    if (!type.startsWith(&quot;.&quot;))\n      type = &quot;.&quot; + type;\n    m_types.add(type.toLowerCase());\n  }\n  \n  \/**\n   * Returns true if the file passes muster,\n   * false otherwise.\n   *\/\n  public boolean accept(File file)\n  {\n    if (file.isDirectory())\n      return true;\n    String name = file.getName().toLowerCase();\n    for (String type: m_types)\n    {\n      if (name.endsWith(type))\n        return true;\n    }\n    return false;\n  }\n\n  \/**\n   * Returns a description for the file set that \n   * this file filter recognizes\n   *\/\n  public String getDescription()\n  {\n    return m_description;\n  }\n  \n  \/**\n   * Sets a description for the file set that this\n   * file filter recognizes.\n   *\/\n  public void setDescription(String description)\n  {\n    m_description = description;\n  }\n  \n  \/\/\/\/\/\/ Private data \/\/\/\/\/\/\n  \n  \/\/ Holds the types that are to be matched.\n  private ArrayList&lt;String&gt; m_types = new ArrayList&lt;String&gt;();\n  private String m_description = &quot;&quot;;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">After you run this&nbsp;<strong>ReadZipFile<\/strong>&nbsp;class, and open a ZIP file, it produces something that looks like this (I opened the Java 5\/1.5&nbsp;<code><strong>src.zip<\/strong><\/code>&nbsp;file, and selected the&nbsp;<strong>java.lang.String<\/strong>&nbsp;class to display):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"650\" height=\"619\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/01\/ZipInp2.jpg\" alt=\"\" class=\"wp-image-180\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/01\/ZipInp2.jpg 650w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/01\/ZipInp2-300x286.jpg 300w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:12px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">If you select a different entry in the combo box at the bottom of the frame, it will display the contents of that file (assuming it to be a text file).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Class_ZipFile\"><\/span>Class ZipFile<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Using_the_ZipFile_Class\"><\/span>Using the&nbsp;<code><strong>ZipFile<\/strong><\/code>&nbsp;Class<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">There is also a&nbsp;<strong>ZipFile<\/strong>&nbsp;class that allows you to access the ZIP file entries directly, rather than having to scan through the entire ZIP file sequentially.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is likely that using the&nbsp;<strong>ZipFile<\/strong>&nbsp;class in place of the&nbsp;<strong>ZipInputStream<\/strong>&nbsp;class could provide better performance.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the same program as above, but with the&nbsp;<strong>ZipInputStream<\/strong>&nbsp;replaced by&nbsp;<strong>ZipFile<\/strong>.&nbsp; It simplifies the code, and appears to improve performance &#8212; at least, on my machine:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage inputOutput;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.IOException;\nimport java.util.Enumeration;\n\nimport java.util.zip.ZipFile;\nimport java.util.zip.ZipEntry;\nimport javax.swing.JComboBox;\nimport javax.swing.JFileChooser;\nimport javax.swing.JFrame;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JMenuItem;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextArea;\nimport javax.swing.UIManager;\n\n\/**\n *   Class to open a ZIP file, and display a list of files\n *   stored within it.\n *   When the user selects a ZIP file, the contents of the\n *   file (assumed to be text) are displayed in the text\n *   area.\n *\n *   @author Bryan J. Higgs, 19 September, 1999\n *\/\npublic class ReadZipFile2 extends JFrame\n{\n  \/**\n   *   Main entry point.\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    try\n    {\n      \/\/ Set the system look and feel\n      UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );\n    } \n    catch (Exception ex)\n    {\n      \/\/ Ignore\n    } \n    \n    ReadZipFile2 frame = new ReadZipFile2();\n    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n    frame.setVisible(true);\n  }\n  \n  \/**\n   *   Constructor.\n   *\/\n  public ReadZipFile2()\n  {\n    setTitle(&quot;ZIP File Reader 2&quot;);\n      \n    \/\/ Set up frame menus\n    JMenuBar menuBar = new JMenuBar();\n    setJMenuBar(menuBar);\n    \n    JMenu fileMenu = new JMenu(&quot;File&quot;);\n    menuBar.add(fileMenu);\n    \n    JMenuItem openItem = new JMenuItem(&quot;Open&quot;);\n    fileMenu.add(openItem);\n    openItem.addActionListener( new OpenAction() );\n    \n    JMenuItem exitItem = new JMenuItem(&quot;Exit&quot;);\n    fileMenu.add(exitItem);\n    exitItem.addActionListener( new ActionListener()\n      {\n        public void actionPerformed(ActionEvent event)\n        {\n          System.exit(0);\n        }\n      }\n    );\n    \n    \/\/ Set the size of the combo box, and\n    \/\/ hook it up to its actions\n    m_fileList.setEditable(false);\n    m_fileList.addItem(&quot;Use File-&gt;Open to select ZIP file&quot;);\n    m_fileList.addActionListener( new ActionListener()\n    {\n      public void actionPerformed(ActionEvent event)\n      {\n        String item = (String) m_fileList.getSelectedItem();\n        if (item != null)\n          loadZipFile(item);\n      }\n    }\n    );\n    m_fileText.setEditable(false);\n    m_fileText.setBackground(Color.WHITE);\n    \n    add(m_fileList, BorderLayout.SOUTH);\n    add(new JScrollPane(m_fileText), BorderLayout.CENTER);\n    pack();\n  }\n  \n  \/**\n   *   Inner class to handle open file events.\n   *\/\n  private class OpenAction implements ActionListener\n  {\n    public void actionPerformed(ActionEvent event)\n    {\n      JFileChooser chooser = new JFileChooser();\n      chooser.setCurrentDirectory( new File(&quot;.&quot;) );\n      TypeFileFilter filter = new TypeFileFilter(&quot;.zip&quot;);\n      filter.setDescription(&quot;ZIP files&quot;);\n      chooser.setFileFilter(filter);\n      int ret = chooser.showOpenDialog(ReadZipFile2.this);\n      if (ret == JFileChooser.APPROVE_OPTION)\n      {\n        String zipFileName = chooser.getSelectedFile().getPath();\n        scanZipFile(zipFileName);\n      }\n    }\n  }\n  \n  \/**\n   * Scans the ZIP file and populates the combo box.\n   *\/\n  public void scanZipFile(String zipFileName)\n  {\n    \/\/ Clean out the list, in case it&#039;s already in use.\n    m_fileList.removeAllItems();\n    \n    ZipEntry entry = null;\n    try\n    {\n      \/\/ Close any previous zip file that\n      \/\/ might have been open.\n      if (m_zipFile != null)\n      {\n        m_zipFile.close();\n        m_zipFile = null;\n      }\n      \/\/ Open the new Zip file\n      m_zipFile = new ZipFile(zipFileName);\n      \/\/ Go through all the entries and\n      \/\/ populate the fileList combo box.\n      Enumeration en = m_zipFile.entries();\n      while (en.hasMoreElements())\n      {\n        entry = (ZipEntry)en.nextElement();\n        m_fileList.addItem(entry.getName());\n      }\n    }\n    catch (IOException ioe)\n    {\n      ioe.printStackTrace();\n    }\n  }\n  \n  \/**\n   *   Displays the files within the ZIP file,\n   *   in the List component.\n   *\/\n  private void loadZipFile(String name)\n  {\n    InputStream in = null;\n    try\n    {\n      \/\/ Get the Zip entry from the already open ZipFile\n      ZipEntry entry = m_zipFile.getEntry(name);\n      if (entry != null)\n      {\n        \/\/ Populate the text area with the contents of the entry.\n        m_fileText.setText(&quot;&quot;);\n        in = m_zipFile.getInputStream(entry);\n        BufferedReader reader = \n                    new BufferedReader(\n                            new InputStreamReader(in));\n        String line;\n        while ( (line = reader.readLine()) != null )\n        {\n          m_fileText.append(line + &quot;\\n&quot;);\n        }\n      }\n    }\n    catch (IOException ioe)\n    {\n      ioe.printStackTrace();\n    }\n    finally\n    {\n      try\n      {\n        if (in != null)\n          in.close();\n      } \n      catch (IOException ex)\n      {\n        \/\/ Ignore\n      }\n    }\n  }\n  \n  \/\/\/\/\/\/\/ Private data \/\/\/\/\/\/\/\/\/\n  \n  private JComboBox m_fileList = new JComboBox();\n  private JTextArea m_fileText = new JTextArea(30, 80);\n  private ZipFile   m_zipFile;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">It produces the same results as the earlier <strong>ReadZipFile<\/strong> program, but with better performance when opening an entry in the file.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"JAR_File_Streams\"><\/span>JAR File Streams<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the JAR File Stream class hiearchy:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">(Package&nbsp;<code><strong>java.util.jar<\/strong><\/code>)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Object<strong>\n    Attributes\n    Attributes.Name\n    Manifest\n    JarEntry\n    JarFile<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">Object\n    InputStream\n        FilterInputStreamCheckedInputStream\n            InflaterInputStream\n                GZIPInputStream\n                ZipInputStream<strong>\n                    JarInputStream\n    <\/strong>OutputStream\n        FilterOutputStreamCheckedOutputStream\n            DeflaterOutputStream\n                GZIPOutputStream\n                ZipOutputStream\n                    <strong>JarOutputStream<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">Object\n    Throwable\n        ExceptionDataFormatExceptionIOExceptionZipException<strong>\n                   JarException<\/strong><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Classes_JarFile_JarEntry\"><\/span>Classes JarFile &amp; JarEntry<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The JAR file support is quite similar to the ZIP file support.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To see just how similar, here is an example of the earlier ZIP program, changed to use the&nbsp;<strong>JarFile<\/strong>&nbsp;and&nbsp;<strong>JarEntry<\/strong>&nbsp;classes:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage inputOutput;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.IOException;\nimport java.util.Enumeration;\nimport java.util.jar.JarEntry;\nimport java.util.jar.JarFile;\nimport java.util.jar.Manifest;\nimport javax.swing.JButton;\n\nimport javax.swing.JComboBox;\nimport javax.swing.JFileChooser;\nimport javax.swing.JFrame;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JMenuItem;\nimport javax.swing.JPanel;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextArea;\nimport javax.swing.UIManager;\n\n\/**\n *   Class to open a JAR file, and display a list of files\n *   stored within it.\n *   When the user selects a JAR file, the contents of the\n *   file (assumed to be text) are displayed in the text\n *   area.\n *\n *   @author Bryan J. Higgs, 19 September, 1999\n *\/\npublic class ReadJarFile extends JFrame\n{\n  \/**\n   *   Main entry point.\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    try\n    {\n      \/\/ Set the system look and feel\n      UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );\n    } \n    catch (Exception ex)\n    {\n      \/\/ Ignore\n    } \n    \n    ReadJarFile frame = new ReadJarFile();\n    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n    frame.setVisible(true);\n  }\n  \n  \/**\n   *   Constructor.\n   *\/\n  public ReadJarFile()\n  {\n    setTitle(&quot;JAR File Reader&quot;);\n      \n    \/\/ Set up frame menus\n    JMenuBar menuBar = new JMenuBar();\n    setJMenuBar(menuBar);\n    \n    JMenu fileMenu = new JMenu(&quot;File&quot;);\n    menuBar.add(fileMenu);\n    \n    JMenuItem openItem = new JMenuItem(&quot;Open&quot;);\n    fileMenu.add(openItem);\n    openItem.addActionListener( new OpenAction() );\n    \n    JMenuItem exitItem = new JMenuItem(&quot;Exit&quot;);\n    fileMenu.add(exitItem);\n    exitItem.addActionListener( new ActionListener()\n      {\n        public void actionPerformed(ActionEvent event)\n        {\n          System.exit(0);\n        }\n      }\n    );\n    \n    \/\/ Set the size of the combo box, and\n    \/\/ hook it up to its actions\n    m_fileList.setEditable(false);\n    m_fileList.addItem(&quot;Use File-&gt;Open to select JAR file&quot;);\n    m_fileList.addActionListener( new ActionListener()\n    {\n      public void actionPerformed(ActionEvent event)\n      {\n        String item = (String) m_fileList.getSelectedItem();\n        if (item != null)\n          loadJarFile(item);\n      }\n    }\n    );\n    m_fileText.setEditable(false);\n    m_fileText.setBackground(Color.WHITE);\n    \n    \/\/ Add a button (inside a JPanel) to the North,\n    \/\/ to allow quick access to the manifest\n    JPanel panel = new JPanel();\n    add(panel, BorderLayout.NORTH);\n    panel.add(m_manifestButton);\n    m_manifestButton.addActionListener( new ActionListener()\n      {\n        public void actionPerformed(ActionEvent event)\n        {\n          loadManifest();\n        }\n      }\n    );\n    \/\/ Disable manifest button until a Jar file is loaded\n    m_manifestButton.setEnabled(false);\n    \n    add(m_fileList, BorderLayout.SOUTH);\n    add(new JScrollPane(m_fileText), BorderLayout.CENTER);\n    pack();\n  }\n  \n  \/**\n   *   Inner class to handle open file events.\n   *\/\n  private class OpenAction implements ActionListener\n  {\n    public void actionPerformed(ActionEvent event)\n    {\n      JFileChooser chooser = new JFileChooser();\n      chooser.setCurrentDirectory( new File(&quot;.&quot;) );\n      TypeFileFilter filter = new TypeFileFilter(&quot;.jar&quot;);\n      filter.setDescription(&quot;JAR files&quot;);\n      chooser.setFileFilter(filter);\n      int ret = chooser.showOpenDialog(ReadJarFile.this);\n      if (ret == JFileChooser.APPROVE_OPTION)\n      {\n        String jarFileName = chooser.getSelectedFile().getPath();\n        scanJarFile(jarFileName);\n      }\n    }\n  }\n  \n  \/**\n   * Scans the JAR file and populates the combo box.\n   *\/\n  public void scanJarFile(String jarFileName)\n  {\n    \/\/ Clean out the list, in case it&#039;s already in use.\n    m_fileList.removeAllItems();\n    \n    JarEntry entry = null;\n    try\n    {\n      \/\/ Close any previous zip file that\n      \/\/ might have been open.\n      if (m_jarFile != null)\n      {\n        m_jarFile.close();\n        m_jarFile = null;\n      }\n      \/\/ Open the new Zip file\n      m_jarFile = new JarFile(jarFileName);\n      \/\/ Go through all the entries and\n      \/\/ populate the fileList combo box.\n      Enumeration en = m_jarFile.entries();\n      while (en.hasMoreElements())\n      {\n        entry = (JarEntry)en.nextElement();\n        m_fileList.addItem(entry.getName());\n      }\n      \/\/ Enable the Get Manifest button\n      m_manifestButton.setEnabled(true);\n    }\n    catch (IOException ioe)\n    {\n      ioe.printStackTrace();\n    }\n  }\n  \n  \/**\n   *   Displays the files within the ZIP file,\n   *   in the text area component.\n   *\/\n  private void loadJarFile(String name)\n  {\n    InputStream in = null;\n    try\n    {\n      \/\/ Get the Jar entry from the already open JarFile\n      JarEntry entry = m_jarFile.getJarEntry(name);\n      if (entry != null)\n      {\n        \/\/ Populate the text area with the contents of the entry.\n        m_fileText.setText(&quot;&quot;);\n        in = m_jarFile.getInputStream(entry);\n        BufferedReader reader = \n                    new BufferedReader(\n                            new InputStreamReader(in));\n        String line;\n        while ( (line = reader.readLine()) != null )\n        {\n          m_fileText.append(line + &quot;\\n&quot;);\n        }\n      }\n    }\n    catch (IOException ioe)\n    {\n      ioe.printStackTrace();\n    }\n    finally\n    {\n      try\n      {\n        if (in != null)\n          in.close();\n      } \n      catch (IOException ex)\n      {\n        \/\/ Ignore\n      }\n    }\n  }\n  \n  \/**\n   * Loads the manifest into the text area\n   *\/\n  private void loadManifest()\n  {\n    m_fileText.setText(&quot;&quot;);\n    Manifest manifest;\n    try\n    {\n      manifest = m_jarFile.getManifest();\n      manifest.write(m_fileOutputStream);\n    } \n    catch (IOException ex)\n    {\n      ex.printStackTrace();\n    }\n  }\n  \n  \/\/\/\/\/\/\/ Private data \/\/\/\/\/\/\/\/\/\n  \n  private JButton   m_manifestButton = new JButton(&quot;Get Manifest&quot;);\n  private JComboBox m_fileList = new JComboBox();\n  private JTextArea m_fileText = new JTextArea(30, 80);\n  private TextAreaOutputStream m_fileOutputStream =\n                                 new TextAreaOutputStream(m_fileText);\n  private JarFile   m_jarFile;\n}\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that I&#8217;m using a convenience class,&nbsp;<strong>TextAreaOutputStream<\/strong>, shown below:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n\/*\n * TextAreaOutputStream.java\n *\n * Created on January 24, 2008\n *\n *\/\n\npackage inputOutput;\n\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport javax.swing.JTextArea;\n\n\/**\n * Class to act as an OutputStream for a text area\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class TextAreaOutputStream extends OutputStream\n{\n  \/**\n   * Creates a new instance of TextAreaOutputStream\n   *\/\n  public TextAreaOutputStream(JTextArea textArea)\n  {\n    m_textArea = textArea;\n  }\n  \n  \/**\n   * Flush the output -- not useful in this case\n   *\/\n  @Override\n  public void flush()\n  { }\n\n  \/**\n   * Close the output -- not useful in this case\n   *\/  \n  @Override\n  public void close()\n  { }\n      \n  \/**\n   * Required override for OutputStream\n   *\n   * Writes the specified byte to this output stream. \n   * The general contract for write is that one byte is written to the output stream. \n   * The byte to be written is the eight low-order bits of the argument b. \n   * The 24 high-order bits of b are ignored.\n   *\n   *\/\n  @Override\n  public void write(int b) throws IOException\n  {\n    if (b == &#039;\\r&#039;)\n      return;\n    \n    if (b == &#039;\\n&#039;)\n    {\n      m_textArea.append(m_sb.toString());\n      m_sb.setLength(0);\n    }\n    \n    m_sb.append((char)b);  \n  }\n  \n  \/\/\/\/\/ Private data \/\/\/\/\/\/\n  \n  private final StringBuilder m_sb = new StringBuilder();\n  private JTextArea m_textArea;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">I&#8217;m using one potentially convenient additional feature of the&nbsp;<strong>JarFile<\/strong>&nbsp;class:&nbsp; the ability to obtain the <strong>Manifest<\/strong> file from the JAR.&nbsp; So, I&#8217;ve added a small GUI feature to the above class to allow you to click a button to view the JAR file&#8217;s manifest:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"650\" height=\"652\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/01\/JarFil3.jpg\" alt=\"\" class=\"wp-image-181\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/01\/JarFil3.jpg 650w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/01\/JarFil3-300x300.jpg 300w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/01\/JarFil3-150x150.jpg 150w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:13px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Here, I ran the program, opened one of my NetBeans&#8217;s project&#8217;s JAR files, and clicked on the <strong>GetManifest<\/strong> button to view the <strong>Manifest<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>ZIP files and JAR (Java Archive) files are very useful, and are heavily used in Java.&nbsp; JAR files are&nbsp;archive files&nbsp;that include a Java-specific&nbsp;manifest file. A manifest file is a&nbsp;metadata&nbsp;file contained within a JAR.&nbsp;It defines extension and package-related data. For example, in JDK 1.5, the code for the Java class library may be found in a [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":67,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_eb_attr":"","ocean_front_end_style_editor":"no","ocean_post_layout":"left-sidebar","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"ocs-course-topics-sidebar","ocean_second_sidebar":"0","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"0","ocean_custom_header_template":"0","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"0","ocean_menu_typo_font_family":"0","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"0","footnotes":""},"class_list":["post-176","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/176","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/comments?post=176"}],"version-history":[{"count":3,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/176\/revisions"}],"predecessor-version":[{"id":183,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/176\/revisions\/183"}],"up":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/67"}],"wp:attachment":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/media?parent=176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}