|
| |
The JAR file support is quite similar to the ZIP file
support.
To see just how similar, here is an example of the
earlier ZIP program, changed to use the JarFile and JarEntry classes:
package inputOutput;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
/**
* Class to open a JAR file, and display a list of files
* stored within it.
* When the user selects a JAR file, the contents of the
* file (assumed to be text) are displayed in the text
* area.
*
* @author Bryan J. Higgs, 19 September, 1999
*/
public class ReadJarFile extends JFrame
{
/**
* Main entry point.
*/
public static void main(String[] args)
{
try
{
// Set the system look and feel
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
}
catch (Exception ex)
{
// Ignore
}
ReadJarFile frame = new ReadJarFile();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
/**
* Constructor.
*/
public ReadJarFile()
{
setTitle("JAR File Reader");
// Set up frame menus
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
JMenuItem openItem = new JMenuItem("Open");
fileMenu.add(openItem);
openItem.addActionListener( new OpenAction() );
JMenuItem exitItem = new JMenuItem("Exit");
fileMenu.add(exitItem);
exitItem.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
System.exit(0);
}
}
);
// Set the size of the combo box, and
// hook it up to its actions
m_fileList.setEditable(false);
m_fileList.addItem("Use File->Open to select JAR file");
m_fileList.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
String item = (String) m_fileList.getSelectedItem();
if (item != null)
loadJarFile(item);
}
}
);
m_fileText.setEditable(false);
m_fileText.setBackground(Color.WHITE);
// Add a button (inside a JPanel) to the North,
// to allow quick access to the manifest
JPanel panel = new JPanel();
add(panel, BorderLayout.NORTH);
panel.add(m_manifestButton);
m_manifestButton.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
loadManifest();
}
}
);
// Disable manifest button until a Jar file is loaded
m_manifestButton.setEnabled(false);
add(m_fileList, BorderLayout.SOUTH);
add(new JScrollPane(m_fileText), BorderLayout.CENTER);
pack();
}
/**
* Inner class to handle open file events.
*/
private class OpenAction implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory( new File(".") );
TypeFileFilter filter = new TypeFileFilter(".jar");
filter.setDescription("JAR files");
chooser.setFileFilter(filter);
int ret = chooser.showOpenDialog(ReadJarFile.this);
if (ret == JFileChooser.APPROVE_OPTION)
{
String jarFileName = chooser.getSelectedFile().getPath();
scanJarFile(jarFileName);
}
}
}
/**
* Scans the JAR file and populates the combo box.
*/
public void scanJarFile(String jarFileName)
{
// Clean out the list, in case it's already in use.
m_fileList.removeAllItems();
JarEntry entry = null;
try
{
// Close any previous zip file that
// might have been open.
if (m_jarFile != null)
{
m_jarFile.close();
m_jarFile = null;
}
// Open the new Zip file
m_jarFile = new JarFile(jarFileName);
// Go through all the entries and
// populate the fileList combo box.
Enumeration en = m_jarFile.entries();
while (en.hasMoreElements())
{
entry = (JarEntry)en.nextElement();
m_fileList.addItem(entry.getName());
}
// Enable the Get Manifest button
m_manifestButton.setEnabled(true);
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
/**
* Displays the files within the ZIP file,
* in the text area component.
*/
private void loadJarFile(String name)
{
InputStream in = null;
try
{
// Get the Jar entry from the already open JarFile
JarEntry entry = m_jarFile.getJarEntry(name);
if (entry != null)
{
// Populate the text area with the contents of the entry.
m_fileText.setText("");
in = m_jarFile.getInputStream(entry);
BufferedReader reader =
new BufferedReader(
new InputStreamReader(in));
String line;
while ( (line = reader.readLine()) != null )
{
m_fileText.append(line + "\n");
}
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
finally
{
try
{
if (in != null)
in.close();
}
catch (IOException ex)
{
// Ignore
}
}
}
/**
* Loads the manifest into the text area
*/
private void loadManifest()
{
m_fileText.setText("");
Manifest manifest;
try
{
manifest = m_jarFile.getManifest();
manifest.write(m_fileOutputStream);
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
/////// Private data /////////
private JButton m_manifestButton = new JButton("Get Manifest");
private JComboBox m_fileList = new JComboBox();
private JTextArea m_fileText = new JTextArea(30, 80);
private TextAreaOutputStream m_fileOutputStream =
new TextAreaOutputStream(m_fileText);
private JarFile m_jarFile;
}
|
Note that I'm using a convenience class, TextAreaOutputStream, which
is shown below:
/*
* TextAreaOutputStream.java
*
* Created on January 24, 2008
*
*/
package inputOutput;
import java.io.IOException;
import java.io.OutputStream;
import javax.swing.JTextArea;
/**
* Class to act as an OutputStream for a text area
*
* @author Bryan Higgs
* @version 1.0
*/
public class TextAreaOutputStream extends OutputStream
{
/**
* Creates a new instance of TextAreaOutputStream
*/
public TextAreaOutputStream(JTextArea textArea)
{
m_textArea = textArea;
}
/**
* Flush the output -- not useful in this case
*/
@Override
public void flush()
{ }
/**
* Close the output -- not useful in this case
*/
@Override
public void close()
{ }
/**
* Required override for OutputStream
*
* Writes the specified byte to this output stream.
* The general contract for write is that one byte is written to the output stream.
* The byte to be written is the eight low-order bits of the argument b.
* The 24 high-order bits of b are ignored.
*
*/
@Override
public void write(int b) throws IOException
{
if (b == '\r')
return;
if (b == '\n')
{
m_textArea.append(m_sb.toString());
m_sb.setLength(0);
}
m_sb.append((char)b);
}
///// Private data //////
private final StringBuilder m_sb = new StringBuilder();
private JTextArea m_textArea;
}
|
I'm using one potentially convenient additional feature of the JarFile
class: the ability to obtain the Manifest file from the JAR. So,
I've added a small GUI feature to the above class to allow you to click a button
to view the JAR file's manifest:

Here, I ran the program, opened one of my NetBeans's project's JAR files, and
clicked on the GetManifest button to view the Manifest.
|