プログラマーの“宿命”? ファイル操作に関する常識プログラマーの常識をJavaで身につける(7)(3/4 ページ)

» 2007年09月12日 00時00分 公開
[伊賀敏樹NTTデータ ビジネスブレインズ]

 ここからは、エクスプローラのメニューで見た機能の中から2つの機能を取り上げます。

 ちなみに、ここで紹介する内容はエクスプローラが提供している機能に相当するものをJava APIを用いて実現するものです。完全に一致した機能ではないという点に留意してください。

ディレクトリ・ファイル一覧を取得するプログラム

 エクスプローラでは、あるディレクトリに含まれるディレクトリおよびファイルの一覧を表示する機能があります。これと同様の機能をJava APIを用いて実現すると、どのようになるのか見てみましょう。

 ディレクトリ内のディレクトリおよびファイルの一覧取得やファイルの詳細情報の取得には、java.io.Fileクラスを利用します。

 加えて、java.io.FileクラスのメソッドのうちgetAbsolutePathメソッドおよびgetCanonicalPathメソッドの動きを確認するための処理を記述しました。絶対パス名正規パス名は、java.io.Fileの利用においてよくつまずきやすいところだからです。

 このように、複数回のJava API呼び出しおよび組み合わせによって、目的の機能が実現できます。

 さらに、入出力処理を実装する場合には、メソッドのパラメータチェックの処理が増える傾向にあります。このサンプルでは、最低限のパラメータチェックを実装しているのにすぎませんが、それでもソースコードのかなりの行数を占めていることを確認してください。

ディレクトリを一覧表示するサンプル
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DirSample {
    public static void main(final String[] args) {
        // パラメータのディレクトリ名は適宜書き替えてください
        new DirSample().dir("C:\\Documents and Settings\\iga");
    }
    public void dir(final String argDirectory) {
        if (argDirectory == null) {
            throw new IllegalArgumentException(
                "パラメータに与えられた処理対象ディレクトリは"
                +"nullでした。しかし、ここにnullを"
                +"与えることはできません。");
        }
        final File targetDirectory = new File(argDirectory);
        if (targetDirectory.exists() == false) {
            throw new IllegalArgumentException(
                "パラメータに与えられた処理対象ディレクトリ["
                 + argDirectory + "]は存在しません。");
        }
        if (targetDirectory.isDirectory() == false) {
            throw new IllegalArgumentException(
                "パラメータに与えられた処理対象ディレクトリ["
                + argDirectory
                + "]は実際にはディレクトリではありません。");
        }
        System.out.println("処理対象ディレクトリ["
                + argDirectory + "]。");
        System.out.println("絶対パス名["
                + targetDirectory.getAbsolutePath() + "]");
        try {
            System.out.println("正規パス名["
                + targetDirectory.getCanonicalPath() + "]");
        } catch (IOException e) {
            System.out.println("正規パス名取得に失敗しました。"
                + e.toString());
            e.printStackTrace();
            return;
        }
        final SimpleDateFormat sdformat = new SimpleDateFormat(
            "yyyy/MM/dd HH:mm:ss");

        final File[] dirContents = targetDirectory.listFiles();
        for (int index = 0; index < dirContents.length; index++) {
            final File fileTarget = dirContents[index];
            final StringBuffer buf = new StringBuffer();

            // 更新日付
            buf.append(sdformat.format(new Date(
                 fileTarget.lastModified())));
            buf.append(" ");

            // ディレクトリである場合には <DIR>
            if (fileTarget.isDirectory()) buf.append("<DIR>");
            else buf.append(" ");
            buf.append(" ");

            // ディレクトリ/ファイル名
            buf.append(fileTarget.getName());
            System.out.println(buf.toString());
        }
    }
}

 実行結果の例を示します。

実行結果

処理対象ディレクトリ[C:\Documents and Settings\iga]。

絶対パス名[C:\Documents and Settings\iga]

正規パス名[C:\Documents and Settings\iga]

2007/04/12 10:50:53 <DIR> .SunDownloadManager

2007/02/14 17:56:36 <DIR> Application Data

2007/08/29 20:45:22 <DIR> Cookies

2007/05/22 08:03:59 dlmgr_.pro

2006/12/22 20:55:20 <DIR> Favorites

2006/08/01 14:57:16 <DIR> Local Settings

2007/08/11 18:07:18 <DIR> My Documents

2007/06/25 10:34:45 <DIR> NetHood

2007/08/30 09:55:59 NTUSER.DAT

2007/08/30 18:30:03 ntuser.dat.LOG

2007/08/30 06:59:52 ntuser.ini

2006/08/01 14:57:16 <DIR> PrintHood

2007/08/30 18:22:43 <DIR> Recent

2007/01/01 08:48:03 <DIR> SendTo

2007/01/05 07:04:03 <DIR> ssh

2006/08/01 15:03:04 <DIR> Templates

2006/12/22 21:06:01 <DIR> UserData

2006/12/23 23:25:22 <DIR> WINDOWS

2007/08/08 22:15:39 <DIR> workspace

2006/12/24 15:19:46 <DIR> スタート メニュー

2007/08/30 09:24:14 <DIR> デスクトップ


 この例では、最終更新日時、ディレクトリかファイルか、ディレクトリ・ファイル名を一覧表示するようになっています。

JUnitでテストをする場合

 また参考までに、このクラスをテストするためのJUnitソースコードを示します。ここでは、主な異常系のみ、しかもなるべく簡潔に記述してある点に注意してください。現実的なJUnitコードはこれよりずっと多くのテストコードによって実現されるものなのです。

編集部注JUnitについて詳しく知りたい読者は@IT情報マネジメント アーキテクチャの記事「EclipseとJUnitによるテスティング」をご参照ください。

import junit.framework.TestCase;

public class DirSampleTest extends TestCase {
    public void testDir() throws Exception {
        try {
            new DirSample().dir(null);
            fail("nullを与えた場合には"
                 +"例外が発生しなくてはなりません。");
        } catch (IllegalArgumentException ex) { }

        try {
            new DirSample().dir("abc");
            fail("存在しないディレクトリを与えた場合には"
                 +"例外が発生しなくてはなりません。");
        } catch (IllegalArgumentException ex) { }

        try {
            new DirSample().dir(".classpath");
            fail("ディレクトリではなくファイルを与えた場合には"
                 +"例外が発生しなくてはなりません。");
        } catch (IllegalArgumentException ex) { }
    }
}

正規パス名を調べるためにディレクトリ名に親ディレクトリを含めるように変更

 ここで、正規パス名とはどういったものであるのかということを確認するために、ディレクトリ名に親ディレクトリを含めるように変更して動作させてみましょう。

public class DirSample {
    public static void main(final String[] args) {
        // パラメータのディレクトリ名は適宜書き替えてください
        new DirSample().dir("C:\\Documents and Settings\\iga\\..");
    }

……以下省略……

 この実行結果から、絶対パス名はディレクトリ名に親ディレクトリ表記が含まれたままですが、正規パス名は親ディレクトリ表記を解消したディレクトリへと変わっていることが分かります(正規パス名の内部的処理については、OSによって動作が異なる場合があります)。

実行結果

処理対象ディレクトリ[C:\Documents and Settings\iga\..]。

絶対パス名[C:\Documents and Settings\iga\..]

正規パス名[C:\Documents and Settings]

2006/12/19 10:50:29 <DIR> Administrator

2006/12/22 20:55:06 <DIR> All Users

……以下省略……


 次ページでは、ファイルコピーの実装例を見ていきます。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。