chapter3_4 ディレクトリとファイルの情報を表示 <source> | Javaをはじめよう

chapter3_4 ディレクトリとファイルの情報を表示 <source>

FileLister.java
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.List;
import java.awt.Panel;
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.FilenameFilter;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;

/**
 * このクラスは、作成したウィンドウに、指定されたディレクトリにあるファイルとサブディレク
 * トリのリストを表示します。リストのエントリをクリックすると、それに関する詳しい情報を
 * 表示します。エントリをダブルクリックすると、ファイルの場合には内容を表示し、ディレクト
 * リの場合には一覧表示を行います。オプション指定されたFilenameFilterは一覧表示のフィルタ
 * 処理を行います。
 */
public class FileLister extends Frame implements ActionListener, ItemListener{
    private List list; //ディレクトリ内容の表示に使うリスト。
    private TextField details; //詳細情報の表示に使います。
    private Panel buttons; //ボタンを保持します。
    private Button up, close; //UpボタンとCloseボタン。
    private File currentDir; //現在一覧表示されているディレクトリ。
    private FilenameFilter filter; //ディレクトリ用のフィルタ。
    private String[] files; //ディレクトリの内容。
    private DateFormat dateFormatter = //日付と時刻の正確な表示に使います。
        DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
    
    /**
     * コンストラクタ: GUIを作成し、初期ディレクトリの内容を一覧表示します。
     */
    public FileLister(String directory, FilenameFilter filter){
        super("File Lister"); //ウィンドウを作成します。
        this.filter = filter; //フィルタがあれば、保存します。
        
        //ユーザがウィンドウを閉じたら、ウィンドウを消します
        addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){ dispose(); }
        });
        
        list = new List(12, false); //リストを設定します。
        list.setFont(new Font("MonoSpaced", Font.PLAIN, 14));
        list.addActionListener(this);
        list.addItemListener(this);
        
        details = new TextField(); //詳細エリアを設定します。
        details.setFont(new Font("MonoSpaced", Font.PLAIN, 12));
        details.setEditable(false);
        
        buttons = new Panel(); //ボタン用パネルを設定します。
        buttons.setLayout(new FlowLayout(FlowLayout.RIGHT, 15, 5));
        buttons.setFont(new Font("SansSerif", Font.BOLD, 14));
        
        up = new Button("Up a Directory"); //ボタンを設定します。
        close = new Button("Close");
        up.addActionListener(this);
        close.addActionListener(this);
        
        buttons.add(up); //ボタン用パネルにボタンを追加します。
        buttons.add(close);
        
        this.add(list, "Center"); //ウィンドウに部品を追加します。
        this.add(details, "North");
        this.add(buttons, "South");
        this.setSize(500, 350);
        
        listDirectory(directory); //初期ディレクトリをリスト表示します。
    }
    
    /**
     * このメソッドはlist()メソッドを使って取得したディレクトリのエントリを
     * Listコンポーネントに表示します。
     */
    public void listDirectory(String directory){
        //文字列をFileオブジェクトに変換し、ディレクトリが存在するか検査します。
        File dir = new File(directory);
        if(!dir.isDirectory())
            throw new IllegalArgumentException("FileLister: no such directory");
        
        //(フィルタ処理された)ディレクトリのエントリを取得します。
        files = dir.list(filter);
        
        //ファイル名のリストをソートします。
        java.util.Arrays.sort(files);
        
        //リストから古いエントリを削除し、新しいエントリを追加します。
        list.removeAll();
        list.add("[Up to Parent Directory]"); //特別なエントリ。
        for(int i = 0; i < files.length; i++) list.add(files[i]);
        
        //ウィンドウのタイトルバーと詳細ボックスにディレクトリ名を表示します。
        this.setTitle(directory);
        details.setText(directory);
        
        //このディレクトリを保持しておきます。
        currentDir = dir;
    }
    
    /**
     * このアイテムリスナメソッドは、Fileの様々なメソッドを使って、ファイルや
     * ディレクトリに関する情報を取得し、表示します。
     */
    public void itemStateChanged(ItemEvent e){
        //Up To Parentを除くために1マイナスします。
        int i = list.getSelectedIndex() - 1; 
        
        if(i < 0) return;
        String filename = files[i]; //選択された項目を取得します。
        File f = new File(currentDir, filename); //Fileに変換します。
        if(!f.exists())
            throw new IllegalArgumentException("FileLister: " +
                                                "no such file or directory");
        //ファイルやディレクトリの詳細を取得し、文字列に連結します。
        String info = filename;
        if(f.isDirectory()) info += File.separator;
        info += " " + f.length() + " bytes ";
        info += dateFormatter.format(new Date(f.lastModified()));
        if(f.canRead()) info += " Read";
        if(f.canWrite()) info += " Write";
        
        //詳細文字列を表示します。
        details.setText(info);
    }
    
    /**
     * エントリがダブルクリックされる、あるいはボタンがクリックされると、このアクション
     * リスナが呼び出されます。ファイルがダブルクリックされた場合、FileViewerを作成して、
     * そのファイルを表示します。ディレクトリがダブルクリックされた場合、listDirectory()
     * を呼んで、ディレクトリを表示します。
     */
    public void actionPerformed(ActionEvent e){
        if(e.getSource() == close) this.dispose();
        else if(e.getSource() == up){ up(); }
        else if(e.getSource() == list){ //項目がダブルクリックされた場合、
            int i = list.getSelectedIndex(); //その項目を検査し、
            if(i == 0) up(); //第1項目であれば親ディレクトリを表示します。
            else{ //そうでなければ、ファイル名を取得します。
                String name = files[i - 1];
                File f = new File(currentDir, name); //Fileに変換します。
                String fullname = f.getAbsolutePath();
                //ディレクトリ内容をリスト表示します。
                if(f.isDirectory()) listDirectory(fullname);
                else new FileViewer(fullname).setVisible(true); //ファイルを表示します。
            }
        }
    }
    
    //親ディレクトリの内容を表示するためのメソッド
    protected void up(){
        String parent = currentDir.getParent();
        if(parent == null) return;
        listDirectory(parent);
    }
    
    //main()が利用するメソッド
    public static void usage(){
        System.out.println("Usage: java FileLister [directory_name] " +
                           "[-e file_extension]");
        System.exit(0);
    }
    
    /**
     * FileListerをスタンドアロンで実行するためのmain()メソッドです。コマンドライン引数
     * を解析し、FileListerオブジェクトを作成します。拡張子が指定された場合、それに対応
     * するFilenameFilterを作成します。ディレクトリが指定されていない場合、カレントディ
     * レクトリを使います。
     */
    public static void main(String[] args) throws IOException{
        FileLister f;
        FilenameFilter filter = null; //フィルタを指定することもできます。
        //ディレクトリが指定されていない場合、カレントディレクトリを使います。
        String directory = null;
        
        //引数配列を順に解析します。
        for(int i = 0; i < args.length; i++){
            if(args[i].equals("-e")){
                if(++i >= args.length) usage();
                //無名クラスで使えるようにfinalにします。
                final String suffix = args[i];
                
                //このクラスは簡単なFilenameFilterです。指定されたファイルを一覧表示
                //するかどうかを判断するためにaccept()メソッドを定義します。ファイル名
                //指定された拡張子を持つ場合、あるいはディレクトリである場合には、
                //一覧を表示します。
                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();
                else directory = args[i];
            }
        }
        
        //ディレクトリの指定がない場合、カレントディレクトリを使います。
        if(directory == null) directory = System.getProperty("user.dir");
        //指定されたディレクトリとフィルタを使ってFileListerオブジェクトを作成します。
        f = new FileLister(directory, filter);
        //ウィンドウを閉じたとき、アプリケーションが終了するように設定します。
        f.addWindowListener(new WindowAdapter(){
            public void windowClosed(WindowEvent e){ System.exit(0); }
        });
        //最後に、ウィンドウを表示します。
        f.setVisible(true);
    }
}