技術とか戦略とか

証券レガシーシステムを8年いじってから転職した普通の文系SEによるブログ。技術のみではなく趣味の戦略考察についても。

java:packageで記述したフォルダ構成を生成するツールを作成してみた

「大量のjavaソースをpackage文で指定されたフォルダに配置するのが面倒」というのは割とどの現場でもあると思うのですが、ググってもそれを解決するツールが見つからなかったので、勉強がてら作成しました。
高度なことはしていないので、Windows環境でJDKが入っていれば動きます。
 
【ソース】
下記をコピペして、javaソースとWindowsバッチを作成する。
 
javaソース(package_tool.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class package_tool {
    public static void main(String args[]){

        // 対象ファイルの特定
        String rootPath=args[0];
        String targetForder="!target";
        String targetFile=args[1];
        String targetFileFull=rootPath+"\\"+targetForder+"\\"+targetFile;

        // package文検索 ※package文がコメント文中で記述されるケースは未対応
        String[] packagePath = null;
        boolean endFlg=false;
        try{
            File file = new File(targetFileFull);
            BufferedReader br = new BufferedReader
                               (new InputStreamReader
                               (new FileInputStream(file),"UTF-8"));
            String str = br.readLine();
            while(str != null && endFlg == false){
                if(str.contains("package")&&str.contains(";")) {
                    String tmp1 = str.replace("package ", "");
                    String tmp2 = tmp1.replace(" ", "");
                    String tmp3 = tmp2.replace(";", "");
                    packagePath = new String[100];
                    packagePath = tmp3.split("\\.", 0);
                    endFlg = true;
                }
                str = br.readLine();
            }
            br.close();
            if(endFlg == false) {
                packagePath = new String[1];
                packagePath[0] = "!unknown";
            }
        }catch(IOException e){
            System.out.println(e);
        }

        // フォルダの作成
        String packageFullPath = rootPath;
        if(endFlg==true) {
         packageFullPath = packageFullPath+"\\"+"!result";
        }
        Runtime runtime = Runtime.getRuntime();
        for(int i = 0; i < packagePath.length; i++){
            packageFullPath = packageFullPath+"\\"+packagePath[i];
            String commandTmp =
                "if not exist "+packageFullPath+"\\ (mkdir "+packageFullPath+")";
            String[] command = { "cmd", "/c", commandTmp};
            try {
                runtime.exec(command);
            } catch (IOException e) {
                System.out.println(e);
            }
        }

        // ファイルの移動
        String fileFullPath = packageFullPath+"\\"+targetFile;
        String commandTmp =
                "move "+targetFileFull+" "+fileFullPath;
        String[] command = { "cmd", "/c", commandTmp};
        try {
            runtime.exec(command);
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}
 
・Windowsバッチ(package_tool.bat)
rem classファイルがなければ作成
if not exist package_tool.class (javac package_tool.java)

rem ツール実行
set pwd=%~dp0
for %%a in (!target\*) do (call :method %%a)
pause
exit
:method
java package_tool %pwd% %~n1%~x1
goto :eof
 
【ファイル・フォルダの配置】
任意のフォルダで、下記のように配置する。

f:id:akira2kun:20180930165228j:plain

 
【使い方】
①!targetフォルダに処理対象のjavaソースを配置
②package_tool.batをダブルクリックで実行
③!resultフォルダにpackage文記載のフォルダ構成が再現され、javaソースも移動する。
④package文が無いjavaソースについては!unknownフォルダへ移動する。
 
【例】
①!targetフォルダに下記ソースを配置
・a.java
import ...
package hoge.fuga.piyo;

public class ...{
}
 
・b.java
import ...
package hoge.fuga.negi;

public class ...{
}
 
・c.java
import ...

public class ...{
}
 
②package_tool.batをダブルクリックで実行
③!resultフォルダを確認
c:\tmp\!result>dir /s
 ドライブ C のボリューム ラベルは XXX です
 ボリューム シリアル番号は XXX です

 c:\tmp\!result のディレクトリ

2018/09/30  16:28    <DIR>          .
2018/09/30  16:28    <DIR>          ..
2018/09/30  16:28    <DIR>          hoge
               0 個のファイル                   0 バイト

 c:\tmp\!result\hoge のディレクトリ

2018/09/30  16:28    <DIR>          .
2018/09/30  16:28    <DIR>          ..
2018/09/30  16:28    <DIR>          fuga
               0 個のファイル                   0 バイト

 c:\tmp\!result\hoge\fuga のディレクトリ

2018/09/30  16:28    <DIR>          .
2018/09/30  16:28    <DIR>          ..
2018/09/30  16:28    <DIR>          negi
2018/09/30  16:28    <DIR>          piyo
               0 個のファイル                   0 バイト

 c:\tmp\!result\hoge\fuga\negi のディレクトリ

2018/09/30  16:28    <DIR>          .
2018/09/30  16:28    <DIR>          ..
2018/09/30  16:23                59 b.java
               1 個のファイル                  59 バイト

 c:\tmp\!result\hoge\fuga\piyo のディレクトリ

2018/09/30  16:28    <DIR>          .
2018/09/30  16:28    <DIR>          ..
2018/09/30  16:14                59 a.java
               1 個のファイル                  59 バイト

     ファイルの総数:
               2 個のファイル                 118 バイト
              14 個のディレクトリ  27,421,794,304 バイトの空き領域

c:\tmp\!result>
 
④!unknownフォルダを確認
c:\tmp\!unknown>dir
 ドライブ C のボリューム ラベルは XXX です
 ボリューム シリアル番号は XXX です

 c:\tmp\!unknown のディレクトリ

2018/09/30  16:28    <DIR>          .
2018/09/30  16:28    <DIR>          ..
2018/09/30  16:24                34 c.java
               1 個のファイル                  34 バイト
               2 個のディレクトリ  27,421,700,096 バイトの空き領域

c:\tmp\!unknown>

---------------------

【2019/03/07 追記】
2回動かせば良い話なので放置していましたが、、
このプログラムには !targetフォルダ から !resultフォルダ へファイルが移動しないことがあるというバグがあります。
原因は、javaのプログラムから呼び出している mkdirコマンド よりも先に moveコマンド が実行されることがあるからです。
これは、以下の記事のようにコマンドの終了を待つようにすれば解消します。
 
java:javaからのOSコマンド呼び出しと注意点

https://akira2kun.hatenablog.com/entry/2019/03/07/230150