LoginSignup
1
2

More than 5 years have passed since last update.

メモ : 【Java】読み込んだcsvを加工(条件で抽出、変更)して出力する 

Last updated at Posted at 2018-07-17

背景

職場の方がラズベリーパイで大気やら紫外線やらのデータを収集しています。
今やっているプロジェクトでグラフ描画するのに、そのデータを拝借してサンプルに使おうと思ったら、
途中に変なデータが混じっていたので、整形しないと使えないなーって書いたコードを書き残します。

haikei.png

こんなデータ

yyyy/mm/dd hh:mm:ss,大気圧(hPa),温度(℃) で0時から23時59分59秒まで毎秒データを取得
たまーに大気圧データの頭に10が付いているデータが混じっている様子

20180712.csv
2018/07/12 00:00:00,1014.44,28.59
2018/07/12 00:00:01,1014.44,28.59
2018/07/12 00:00:02,1014.46,28.62
2018/07/12 00:00:03,1014.45,28.62
2018/07/12 00:00:04,1014.44,28.59
2018/07/12 00:00:05,1014.45,28.62
2018/07/12 00:00:06,101014.45,28.59
2018/07/12 00:00:07,1014.45,28.62

      ~ 中略 ~

2018/07/12 23:59:58,1006.29,28.66
2018/07/12 23:59:59,1006.28,28.62

やりたいこと

CSVを読み込んで、必要な加工をして、別名のCSVに出力したい。
- 毎秒は不要なので1分毎のデータを書き出したい。(毎分00秒だけ抽出する)
- 00秒の大気圧データに101014.45みたいな数値が入っていたら1014.45に直してデータを書き出したい。

完成したコード

test.java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class test{

    public static void main(String[] args) {
        process("20180712.csv",  ":00,","output.csv");
    }

    public static void process(String read_file, String searchString, String output_file){

        try(FileReader fr = new FileReader(read_file);BufferedReader br = new BufferedReader(fr);
            FileWriter fw = new FileWriter(output_file);BufferedWriter bw = new BufferedWriter(fw)){

            String line;
            while ((line = br.readLine()) != null) {
                Pattern p = Pattern.compile(searchString);
                Matcher m = p.matcher(line);
                if (m.find()){
                    String[] csvArray;
                    csvArray = line.split(",");
                    String time  = csvArray[0];
                    float press = Float.parseFloat(csvArray[1])%10000;
                    String pressure = String.format("%.2f", press);
                    String temperature  = csvArray[2];
                    String outputLine = String.join(",",time,pressure,temperature);
                    bw.write(outputLine);
                    bw.newLine();
                }else{ 
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

:pencil: やっていること 

  processに読込むファイル名 , 検索文字 , 出力ファイル名 の3つの引数を渡してます。
    process("20180712.csv", ":00,","output.csv");

❶ Pattern と Matcher を使用して 0秒(":00,") の行を検索
❷ 00秒を含む行が見つかったら、Stringの配列(csvArray)に , (カンマ) でsplitして入れる
❸ 大気圧データ(csvArray[1])は小数なのでString型からfloat型に変換する
  ※ついでに10000で割った 余りを値に設定する。101014.45を10000で割ると余りは1014.45
❹ float型のデータを再度String型に変換する
  ※ついでに小数第二位以下を四捨五入して値に設定する。
❺ 各配列の値を, (カンマ) で繋げる
❻ 1行出力して改行する

❶~❻までを読込むファイルの行数分繰り返す


:pencil: メモ 

検索するのに使った Pattern と Matcher

MatcherはPattern.matcher()メソッドに文字列を渡して作成できる。
マッチ判定の結果がtrueかfalseで返される。

Pattern pattern = Pattern.compile("う"); //検索したい文字列 "う" を設定する Pattern を作成
Matcher matcher = pattern.matcher("あいうえお"); //検索対象の文字列 "あいうえお" を検索対象にするよっていう matcher を作成

matcher.find()       // 部分的にマッチするかの判定
matcher.lookingAt()  // 先頭からマッチするかの判定
matcher.matches()    // 完全にマッチするかの判定
関数電卓

はじめてWindowsの標準電卓以外の電卓機能を使ったのでメモ
電卓.png

101014.45を10000で割ったときのあまりを求める時
101014.45 Mod 10000 = 1014.45
関数電卓.png

1
2
0

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
1
2