Excelなどの表計算ソフトなどで以下のような表を作成したことがあるだろう。
このデータをプログラムで扱いたい。そんな時に便利なのがCSV形式である。
CSVとはComma-Separated Valuesの略でデータをカンマ区切りで表す汎用データフォーマットの一つだ。
例外なくすべての表計算ソフトでCSV形式で出力することができる。実際に先ほどのデータをCSV形式で保存したものが以下だ。
●sample.csv
年度,製品A,製品B 2016,210,1014 2017,220,990
行ごとに改行され、項目がカンマで区切られているのがわかる。
一般的に拡張子には.csvが用いられる。
このような汎用データフォーマットにはこのほかにもTSV、XML、JSONなど様々なものがあるがまずはこのもっともポピュラーなCSVデータをプログラムで扱ってみよう。
今回はJavaで扱ってみる。このように汎用データフォーマットをプログラムで扱えるようにすることを「パースする」などとも言うので覚えておくと良い。今回はjavaによるCSVパースだ。
1.まずは以下から先ほど作成したCSVファイルをダウンロードする。(文字コードはUTF-8)
下をクリック
2.ダウンロードしたファイルをJavaのプロジェクトルートに配置する。
3.以下のソースコードを打ち込む
●Sales.java
public class Sales{ private String year; private int salesA; private int salesB; public Sales(String year,int salesA,int salesB){ this.year=year; this.salesA=salesA; this.salesB=salesB; } @Override public String toString() { return String.format("%s年度の製品Aの売上高%d、製品Bの売上高%d", this.year,this.salesA,this.salesB); } }
●CSVParseLesson.java
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; public class CSVParseLesson { public static void main(String[] args) { //今回はcsvデータをパースしてSalesクラスインスタンスを生成し、それをlistに格納する List<Sales> list=new ArrayList<>(); //ファイルをバッファリングして読み込むBufferedReader型の変数を宣言 BufferedReader br=null; try { //csvファイルを指定し、fisを生成する FileInputStream fis=new FileInputStream("sample.csv"); //InputStreamReaderでラッピング(csvファイルの文字コードを指定する) InputStreamReader isr=new InputStreamReader(fis,"UTF-8"); //BufferdReaderクラスのインスタンスをnew br=new BufferedReader(isr); //ファイルを一行一行読み込みながらファイルの終わりまで処理をするときの定型 String line; while((line=br.readLine()) != null){ //最初の一行は見出しが入っている行なのでスキップする if(line.startsWith("年度")){ continue; } //文字列.split(",")で文字列をカンマによって分解し、配列を生成できる。 //2016,210,1014=>data[0]は"2016",data[1]は"210",data[2]は"1014" String[] data=line.split(","); //インスタンスを生成し、リストに格納する。salesAとsalesBはintなのでintに変換する list.add(new Sales(data[0],Integer.parseInt(data[1]),Integer.parseInt(data[2]))); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if(br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } //csvパースによって作成されたlistを出力する for(Sales s:list){ System.out.println(s); } } }
4. 実行すると以下のように出力されることを確認する。
2016年度の製品Aの売上高210、製品Bの売上高1014 2017年度の製品Aの売上高220、製品Bの売上高990
ファイルの読み込みとStringクラスに用意されているsplitメソッドを使うと簡単にCSVファイルをパースできることが確認できた。
CSVデータの扱いを理解したところで、以下の問題に挑戦してみよう。
Q1
先ほどの例題において今度は2018〜2025年度のデータをJavaプログラムによって作成し、sample2.csvファイルに書き込め。
各年の製品Aの売り上げは180~250のランダム、製品Bの売り上げは800〜1300のランダムとする。
なお、ファイル文字コードはUTF-8で書き込むこと。
[作成されたsample2.csvファイルの一例]
年度,製品A,製品B 2018,184,894 2019,214,996 2020,221,1296 2021,187,1053 2022,240,821 2023,211,877 2024,222,1038 2025,206,1174
●Sales.javaに追記
class Sales{ private String year; private int salesA; private int salesB; public Sales(String year,int salesA,int salesB){ this.year=year; this.salesA=salesA; this.salesB=salesB; } @Override public String toString() { return String.format("%s年度の製品Aの売上高%d、製品Bの売上高%d", this.year,this.salesA,this.salesB); } public String toCSV(){ return String.format("%s,%d,%d",this.year,this.salesA,this.salesB); }
●CSVFileWriteLesson.java
import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.Random; public class CSVFileWriteLesson { public static void main(String[] args) { Random r=new Random(); List<Sales> list=new ArrayList<>(); for(int i=2018;i<=2025;i++){ int salesA=r.nextInt(250-180+1)+180; int salesB=r.nextInt(1300-800+1)+800; list.add(new Sales(String.valueOf(i),salesA,salesB)); } BufferedWriter bw=null; try { FileOutputStream fos=new FileOutputStream("sample2.csv"); OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8"); bw=new BufferedWriter(osw); bw.append("年度,製品A,製品B"); bw.newLine(); for(Sales s:list){ bw.append(s.toCSV()); bw.newLine(); } bw.flush(); System.out.println("書き込み完了"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if(bw != null){ try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
コメント