FileLister.java Source code

Java tutorial

Introduction

Here is the source code for FileLister.java

Source

/*
 * Copyright (c) 2004 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 3nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose,
 * including teaching and use in open-source projects.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book, 
 * please visit http://www.davidflanagan.com/javaexamples3.
 */

import java.awt.Button;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.DateFormat;

/**
 * This class creates and displays a window containing a list of files and
 * sub-directories in a specified directory. Clicking on an entry in the list
 * displays more information about it. Double-clicking on an entry displays it,
 * if a file, or lists it if a directory. An optionally-specified FilenameFilter
 * filters the displayed list.
 */
public class FileLister extends Frame implements ActionListener, ItemListener {
    private List list; // To display the directory contents in

    private TextField details; // To display detail info in.

    private Panel buttons; // Holds the buttons

    private Button up, close; // The Up and Close buttons

    private File currentDir; // The directory currently listed

    private FilenameFilter filter; // An optional filter for the directory

    private String[] files; // The directory contents

    private DateFormat dateFormatter = // To display dates and time correctly
            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);

    /**
     * Constructor: create the GUI, and list the initial directory.
     */
    public FileLister(String directory, FilenameFilter filter) {
        super("File Lister"); // Create the window
        this.filter = filter; // Save the filter, if any

        // Destroy the window when the user requests it
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                dispose();
            }
        });

        list = new List(12, false); // Set up the list
        list.setFont(new Font("MonoSpaced", Font.PLAIN, 14));
        list.addActionListener(this);
        list.addItemListener(this);

        details = new TextField(); // Set up the details area
        details.setFont(new Font("MonoSpaced", Font.PLAIN, 12));
        details.setEditable(false);

        buttons = new Panel(); // Set up the button box
        buttons.setLayout(new FlowLayout(FlowLayout.RIGHT, 15, 5));
        buttons.setFont(new Font("SansSerif", Font.BOLD, 14));

        up = new Button("Up a Directory"); // Set up the two buttons
        close = new Button("Close");
        up.addActionListener(this);
        close.addActionListener(this);

        buttons.add(up); // Add buttons to button box
        buttons.add(close);

        this.add(list, "Center"); // Add stuff to the window
        this.add(details, "North");
        this.add(buttons, "South");
        this.setSize(500, 350);

        listDirectory(directory); // And now list initial directory.
    }

    /**
     * This method uses the list() method to get all entries in a directory and
     * then displays them in the List component.
     */
    public void listDirectory(String directory) {
        // Convert the string to a File object, and check that the dir exists
        File dir = new File(directory);
        if (!dir.isDirectory())
            throw new IllegalArgumentException("FileLister: no such directory");

        // Get the (filtered) directory entries
        files = dir.list(filter);

        // Sort the list of filenames.
        java.util.Arrays.sort(files);

        // Remove any old entries in the list, and add the new ones
        list.removeAll();
        list.add("[Up to Parent Directory]"); // A special case entry
        for (int i = 0; i < files.length; i++)
            list.add(files[i]);

        // Display directory name in window titlebar and in the details box
        this.setTitle(directory);
        details.setText(directory);

        // Remember this directory for later.
        currentDir = dir;
    }

    /**
     * This ItemListener method uses various File methods to obtain information
     * about a file or directory. Then it displays that info.
     */
    public void itemStateChanged(ItemEvent e) {
        int i = list.getSelectedIndex() - 1; // minus 1 for Up To Parent entry
        if (i < 0)
            return;
        String filename = files[i]; // Get the selected entry
        File f = new File(currentDir, filename); // Convert to a File
        if (!f.exists()) // Confirm that it exists
            throw new IllegalArgumentException("FileLister: " + "no such file or directory");

        // Get the details about the file or directory, concatenate to a string
        String info = filename;
        if (f.isDirectory())
            info += File.separator;
        info += " " + f.length() + " bytes ";
        info += dateFormatter.format(new java.util.Date(f.lastModified()));
        if (f.canRead())
            info += " Read";
        if (f.canWrite())
            info += " Write";

        // And display the details string
        details.setText(info);
    }

    /**
     * This ActionListener method is invoked when the user double-clicks on an
     * entry or clicks on one of the buttons. If they double-click on a file,
     * create a FileViewer to display that file. If they double-click on a
     * directory, call the listDirectory() method to display that directory
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == close)
            this.dispose();
        else if (e.getSource() == up) {
            up();
        } else if (e.getSource() == list) { // Double click on an item
            int i = list.getSelectedIndex(); // Check which item
            if (i == 0)
                up(); // Handle first Up To Parent item
            else { // Otherwise, get filename
                String name = files[i - 1];
                File f = new File(currentDir, name); // Convert to a File
                String fullname = f.getAbsolutePath();
                if (f.isDirectory())
                    listDirectory(fullname); // List dir
                else
                    new FileViewer(fullname).show(); // display file
            }
        }
    }

    /** A convenience method to display the contents of the parent directory */
    protected void up() {
        String parent = currentDir.getParent();
        if (parent == null)
            return;
        listDirectory(parent);
    }

    /** A convenience method used by main() */
    public static void usage() {
        System.out.println("Usage: java FileLister [directory_name] " + "[-e file_extension]");
        System.exit(0);
    }

    /**
     * A main() method so FileLister can be run standalone. Parse command line
     * arguments and create the FileLister object. If an extension is specified,
     * create a FilenameFilter for it. If no directory is specified, use the
     * current directory.
     */
    public static void main(String args[]) throws IOException {
        FileLister f;
        FilenameFilter filter = null; // The filter, if any
        String directory = null; // The specified dir, or the current dir

        // Loop through args array, parsing arguments
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-e")) {
                if (++i >= args.length)
                    usage();
                final String suffix = args[i]; // final for anon. class below

                // This class is a simple FilenameFilter. It defines the
                // accept() method required to determine whether a specified
                // file should be listed. A file will be listed if its name
                // ends with the specified extension, or if it is a directory.
                filter = new FilenameFilter() {
                    public boolean accept(File dir, String name) {
                        if (name.endsWith(suffix))
                            return true;
                        else
                            return (new File(dir, name)).isDirectory();
                    }
                };
            } else {
                if (directory != null)
                    usage(); // If already specified, fail.
                else
                    directory = args[i];
            }
        }

        // if no directory specified, use the current directory
        if (directory == null)
            directory = System.getProperty("user.dir");
        // Create the FileLister object, with directory and filter specified.
        f = new FileLister(directory, filter);
        // Arrange for the application to exit when the window is closed
        f.addWindowListener(new WindowAdapter() {
            public void windowClosed(WindowEvent e) {
                System.exit(0);
            }
        });
        // Finally, pop the window up up.
        f.show();
    }
}

class FileViewer extends Frame implements ActionListener {
    String directory; // The default directory to display in the FileDialog

    TextArea textarea; // The area to display the file contents into

    /** Convenience constructor: file viewer starts out blank */
    public FileViewer() {
        this(null, null);
    }

    /** Convenience constructor: display file from current directory */
    public FileViewer(String filename) {
        this(null, filename);
    }

    /**
     * The real constructor. Create a FileViewer object to display the specified
     * file from the specified directory
     */
    public FileViewer(String directory, String filename) {
        super(); // Create the frame

        // Destroy the window when the user requests it
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                dispose();
            }
        });

        // Create a TextArea to display the contents of the file in
        textarea = new TextArea("", 24, 80);
        textarea.setFont(new Font("MonoSpaced", Font.PLAIN, 12));
        textarea.setEditable(false);
        this.add("Center", textarea);

        // Create a bottom panel to hold a couple of buttons in
        Panel p = new Panel();
        p.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 5));
        this.add(p, "South");

        // Create the buttons and arrange to handle button clicks
        Font font = new Font("SansSerif", Font.BOLD, 14);
        Button openfile = new Button("Open File");
        Button close = new Button("Close");
        openfile.addActionListener(this);
        openfile.setActionCommand("open");
        openfile.setFont(font);
        close.addActionListener(this);
        close.setActionCommand("close");
        close.setFont(font);
        p.add(openfile);
        p.add(close);

        this.pack();

        // Figure out the directory, from filename or current dir, if necessary
        if (directory == null) {
            File f;
            if ((filename != null) && (f = new File(filename)).isAbsolute()) {
                directory = f.getParent();
                filename = f.getName();
            } else
                directory = System.getProperty("user.dir");
        }

        this.directory = directory; // Remember the directory, for FileDialog
        setFile(directory, filename); // Now load and display the file
    }

    /**
     * Load and display the specified file from the specified directory
     */
    public void setFile(String directory, String filename) {
        if ((filename == null) || (filename.length() == 0))
            return;
        File f;
        FileReader in = null;
        // Read and display the file contents. Since we're reading text, we
        // use a FileReader instead of a FileInputStream.
        try {
            f = new File(directory, filename); // Create a file object
            in = new FileReader(f); // And a char stream to read it
            char[] buffer = new char[4096]; // Read 4K characters at a time
            int len; // How many chars read each time
            textarea.setText(""); // Clear the text area
            while ((len = in.read(buffer)) != -1) { // Read a batch of chars
                String s = new String(buffer, 0, len); // Convert to a string
                textarea.append(s); // And display them
            }
            this.setTitle("FileViewer: " + filename); // Set the window title
            textarea.setCaretPosition(0); // Go to start of file
        }
        // Display messages if something goes wrong
        catch (IOException e) {
            textarea.setText(e.getClass().getName() + ": " + e.getMessage());
            this.setTitle("FileViewer: " + filename + ": I/O Exception");
        }
        // Always be sure to close the input stream!
        finally {
            try {
                if (in != null)
                    in.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * Handle button clicks
     */
    public void actionPerformed(ActionEvent e) {
        String cmd = e.getActionCommand();
        if (cmd.equals("open")) { // If user clicked "Open" button
            // Create a file dialog box to prompt for a new file to display
            FileDialog f = new FileDialog(this, "Open File", FileDialog.LOAD);
            f.setDirectory(directory); // Set the default directory

            // Display the dialog and wait for the user's response
            f.show();

            directory = f.getDirectory(); // Remember new default directory
            setFile(directory, f.getFile()); // Load and display selection
            f.dispose(); // Get rid of the dialog box
        } else if (cmd.equals("close")) // If user clicked "Close" button
            this.dispose(); // then close the window
    }

    /**
     * The FileViewer can be used by other classes, or it can be used standalone
     * with this main() method.
     */
    static public void main(String[] args) throws IOException {
        // Create a FileViewer object
        Frame f = new FileViewer((args.length == 1) ? args[0] : null);
        // Arrange to exit when the FileViewer window closes
        f.addWindowListener(new WindowAdapter() {
            public void windowClosed(WindowEvent e) {
                System.exit(0);
            }
        });
        // And pop the window up
        f.show();
    }
}