業務上、列数が膨大なCSVを扱うことがあり、
そのうちいくつかの列の値だけをちょこっと確認したい・・と思うことが稀によくあります。
必要な列だけを抽出して扱えるようになれば私が喜ぶぞォ~!!と思い、
コマンドラインで動くJavaプログラムを作ってみました。
#やりたいこと
こんなCSVがあった場合、
game.csv
1,Splatoon 2,Nintendo,Nintendo Switch,2017年7月21日
2,Yakuza: Like a Dragon,SEGA,PlayStation 4,2020年1月16日
3,Undertale,Toby Fox,PlayStation 4,2015年9月15日
4,Fire Emblem: Three Houses,Nintendo,Nintendo Switch,2019年7月26日
5,Ghost of Tsushima,Sony,PlayStation 4,2020年7月17日
ある時は、↓こんな感じで2列目と3列目を取得したい。
Splatoon 2,Nintendo
Yakuza: Like a Dragon,SEGA
Undertale,Toby Fox
Fire Emblem: Three Houses,Nintendo
Ghost of Tsushima,Sony
でも場合によっては、↓こんな感じに1列目・2列目・5列目を取得したい。
1,Splatoon 2,2017年7月21日
2,Yakuza: Like a Dragon,2020年1月16日
3,Undertale,2015年9月15日
4,Fire Emblem: Three Houses,2019年7月26日
5,Ghost of Tsushima,2020年7月17日
つまり・・必要に応じて指定した列の値だけを抽出した~い!
#つくった
つくりました。
GetSpecifiedColumn.java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 指定したCSVから特定列の値のみを抽出します.
* 抽出結果のファイルは「【抽出済】対象ファイル名」の名前で同階層に出力されます.
*
* 引数1:対象ファイル
* 引数2:取得したい列番号(0始まり、カンマ区切りで複数指定が可能)
*/
public class GetSpecifiedColumn{
public static void main(String[] args){
// コマンドライン引数を取得.
String path = null;
List<String> colList = new ArrayList<String>();
if (args.length == 2){
path = args[0];
colList = new ArrayList<String>(Arrays.asList(args[1].split(",")));
} else {
System.out.println("引数間違ってるよ!");
return;
}
try{
// 入力ファイル.
File inFile = new File(path);
BufferedReader br = new BufferedReader(new FileReader(inFile));
// 出力ファイル.
File outFile = new File("【抽出済】"+ path);
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
// 列番号の最大値(最終列の番号)を取得.
String lastCol = colList.get(colList.size() - 1);
String line = null;
// CSVファイルを1行毎に読み込む.
while( (line = br.readLine()) != null) {
String[] strList = line.split(",",0); // 行データを配列化.
// 特定列だけを出力.
for (String col : colList) {
if (!col.equals(lastCol)) {
// 最終列でない場合は、改行なし・カンマありで出力.
pw.print(strList[Integer.parseInt(col)]);
pw.print(",");
} else {
// 最終列の場合は、改行あり・カンマなしで出力.
pw.println(strList[Integer.parseInt(col)]);
}
}
}
br.close();
pw.close();
} catch(IOException e) {
System.out.println(e);
}
System.out.println("処理完了!YATTA!");
}
}
#うごかす
コンパイル
javac -encoding UTF-8 GetSpecifiedColumn.java
実行
java GetSpecifiedColumn game.csv 0,1,4
実行結果
【抽出済】game.csv
1,Splatoon 2,2017年7月21日
2,Yakuza: Like a Dragon,2020年1月16日
3,Undertale,2015年9月15日
4,Fire Emblem: Three Houses,2019年7月26日
5,Ghost of Tsushima,2020年7月17日
YATTA!
その後、無事業務データでも問題なく動作することを確認しました。わ~い!
#補足
個人用途のため細々した制御は入れていません!ご注意ください。
※対象CSVのデータ部に「,(カンマ)」が含まれているとうまく動かない。存在しないCSVファイル名や、対象CSVに存在しない列番号を指定すると例外になるなど。