LoginSignup
2
0

More than 3 years have passed since last update.

CSVファイルから特定列の値だけを抽出したい

Posted at

業務上、列数が膨大な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に存在しない列番号を指定すると例外になるなど。

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0