2015年1月25日日曜日

[Java][batch]Javaプログラムをバッチファイルから実行する(FileFinder)

別の記事で掲載したAppMainから呼び出す、共通インターフェースを実装する、個別クラスについて記述する。

ここでは所定のフォルダ配下を再帰的に検索し、指定した名前のファイルを見つけるユーティリティクラスをサンプルとする。
バッチから呼び出されるクラスを作るときに注意しなければならないことは、メッセージボックスなどのプログラムを「止める」処理を書いてはいけないということである。

また、実際にバッチファイルから実行して何か問題が起きた時、調査は原則としてログから行うより他ない。処理ルートのどこを通ったか分かるようにしておかないと、ログを見ても問題が起きた場所が分からない。

ただしログの量は多くなりすぎないようにすることも重要である。処理を中断せざるを得ない致命的エラーの箇所全てと、正常に処理が進んだときのチェックポイントにログを配置したい。

<以下、ソースコード>
package cmd;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.apache.log4j.Logger;

import exception.AppException;

/**
 * ファイル検索
 */
public class FileFinder implements CommandInterface {

    /** ログ */
    private final Logger log = Logger.getLogger(this.getClass());

    /** 結果出力ファイル */
    private BufferedWriter resultFile;

    /**
     * コマンドラインインターフェースです。 <br>
     * 本クラスの機能をバッチから呼び出す場合は、このメソッドを実行します。
     *
     * @param args
     *            コマンドライン引数
     * @throws Exception
     */
    @Override
    public void doMain(String[] args) throws AppException {

        // コマンドライン引数が指定されていない場合は、エラーとする
        if (args == null || args.length == 0) {
            throw new AppException("コマンドライン引数がありません。");
        }

        // 第1引数が自クラスを指していない場合は、エラーとする
        if (!args[0].contains(this.getClass().getName())) {
            throw new AppException("不正な呼び出しです。  args[0] : " + args[0]);
        }

        // 引数が足りない場合は、エラーとする
        String paramName1 = "検索対象ディレクトリ名";
        String paramName2 = "検索するファイル名";
        String paramName3 = "結果出力ファイル名";
        if (args.length < 4) {
            throw new AppException("引数が足りません。  (第1引数 " + paramName1 + ", 第2引数 "
                    + paramName2 + ", 第3引数 " + paramName3 + ")");
        }

        // 引数をログに記録する
        String crlf = System.getProperty("line.separator");
        String msg = "ファイル検索" + crlf + "\t" + paramName1 + " : " + args[1]
                + crlf + "\t" + paramName2 + " : " + args[2] + crlf + "\t"
                + paramName3 + " : " + args[3];
        log.info(msg);

        // ファイル検索を実行する
        doFindFile(args[1], args[2], args[3]);
    }

    /**
     * ファイル検索を行います。
     *
     * @param targetDirName
     *            検索対象ディレクトリ名
     * @param searchFileName
     *            検索するファイル名
     * @param resultFileName
     *            結果出力ファイル名
     * @throws AppException
     */
    public void doFindFile(String targetDirName, String searchFileName,
            String resultFileName) throws AppException {

        // 検索対象ディレクトリが存在しない場合は、エラーとする
        File targetDir = new File(targetDirName);
        if (!(targetDir.exists() && targetDir.isDirectory())) {
            throw new AppException("検索対象ディレクトリが存在しません。  " + targetDirName);
        }

        try {
            // 結果出力ファイルを作成する
            resultFile = new BufferedWriter(new FileWriter(new File(
                    resultFileName)));
            resultFile.write("次のフォルダ配下を検索します。  " + targetDirName);
            resultFile.newLine();
            resultFile.newLine();

            // ファイル検索を実行する
            doFindFileRecursive(searchFileName, targetDir);

        } catch (IOException e) {
            throw new AppException(e);

        } finally {

            try {
                // 最後に必ずファイルを閉じる
                if (resultFile != null) {
                    resultFile.close();
                }
                resultFile = null;

            } catch (IOException e) {
                throw new AppException(e);
            }
        }
    }

    /**
     * ディレクトリを再帰的にたどって、ファイルを検索します。
     *
     * @param searchFileName
     *            検索するファイル名
     * @param currentDir
     *            現在のディレクトリ
     * @throws IOException
     */
    private void doFindFileRecursive(String searchFileName, File currentDir)
            throws IOException {

        // ディレクトリ内にファイルがなければ、処理を終了する
        File[] files = currentDir.listFiles();
        if (files == null || files.length == 0) {
            return;
        }

        // ディレクトリ内の全てのファイルを処理するまでループ
        for (File file : files) {

            if (file.isDirectory()) {

                // ディレクトリの場合は、本処理を再帰的に呼び出す
                doFindFileRecursive(searchFileName, file);

            } else {

                // ファイルの場合は、パターンにマッチするか判定を行う
                if (!file.getName().matches(searchFileName)) {
                    continue;
                }

                // ファイルが見つかったら結果出力ファイルに書き込みを行う
                resultFile.write(file.getParentFile().getAbsolutePath());
                resultFile.newLine();
                resultFile.write("\t" + file.getName());
                resultFile.newLine();
            }
        }
    }
}

0 件のコメント:

コメントを投稿