2015年1月25日日曜日

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

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

FileFinderと同じようなクラスだが、ここでは所定のフォルダ配下を再帰的に検索し、指定した名前のファイルを見つけたら、別のディレクトリにコピーするユーティリティクラスをサンプルとする。

FileFinderと本クラスの2クラスのサンプルを記載したのは、同じ1つのバッチ呼び出しの入り口から異なる2つ以上の機能を呼び出すことができることを例示するためである。

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

import java.io.File;

import org.apache.log4j.Logger;

import exception.AppException;

public class FilePicker implements CommandInterface {

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

    /** 結果出力ディレクトリ */
    private File resultDir;

    /**
     * コマンドラインインターフェースです。 <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);

        // ファイル抽出を実行する
        doPickupFile(args[1], args[2], args[3]);
    }

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

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

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

        // ファイル抽出を実行する
        doPickupFileRecursive(searchFileName, targetDir, resultDir);
    }

    /**
     * ディレクトリを再帰的にたどって、ファイルをコピーします。
     *
     * @param searchFileName
     *            検索するファイル名
     * @param currentDir
     *            カレントディレクトリ
     * @param currentResultDir
     *            カレント結果出力ディレクトリ
     * @throws AppException
     */
    private void doPickupFileRecursive(String searchFileName, File currentDir,
            File currentResultDir) throws AppException {

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

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

            if (file.isDirectory()) {

                // ディレクトリの場合は、結果出力先に同じディレクトリを作成する
                File resultDir = new File(currentResultDir.getAbsolutePath()
                        + File.separator + file.getName());
                if (!resultDir.exists()) {
                    resultDir.mkdirs();
                }

                // 本処理を再帰的に呼び出す
                doPickupFileRecursive(searchFileName, file, resultDir);

            } else {

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

                // ファイルが見つかったらログファイルに書き込みを行う
                String destFileName = currentResultDir.getAbsolutePath()
                        + File.separator + file.getName();
                String crlf = System.getProperty("line.separator");
                String msg = "ファイルをコピーします。" + crlf + "\tコピー元 : "
                        + file.getAbsolutePath() + crlf + "\tコピー先 : "
                        + destFileName;
                log.info(msg);

                // ファイルをコピーする
                copyFile(file.getAbsolutePath(), destFileName);
            }
        }
    }

    /**
     * ファイルをコピーします。
     *
     * @param srcFileName
     *            コピー元ファイル名
     * @param destFileName
     *            コピー先ファイル名
     */
    private void copyFile(String srcFileName, String destFileName)
            throws AppException {

        // ファイルエンコード(文字化け)の問題があるため、copyコマンドでコピーする
        String[] cmd = { "cmd", "/c", "copy", srcFileName, destFileName };
        ProcessBuilder pb = new ProcessBuilder(cmd);
        Process process;
        try {
            process = pb.start();
            process.waitFor();

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

0 件のコメント:

コメントを投稿