読者です 読者をやめる 読者になる 読者になる

CSV書込み(2)

CSV書込み、(1) - Oboe吹きプログラマの黙示録

のつづきです。

net.sf.csv4j.CSVWriter を使い、ヘッダ行もデータ行も呼び出し側の与えるデータの問題だと割り切って考えて

以下の関数型インターフェースを用意すれば、とても簡潔になる。

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Collection;
import java.util.function.Supplier;
import net.sf.csv4j.CSVWriter;

/**
 * CSV生成インターフェース.
 */
@FunctionalInterface
public interface CsvCreator extends Serializable{

   public Supplier<Collection<String[]>> getLineElements();

   default public void create(OutputStream out, String charName){
      try(OutputStreamWriter writer = new OutputStreamWriter(out, charName)){
         CSVWriter csvWriter = new CSVWriter(writer);
         for(String[] s:getLineElements().get()){
            csvWriter.writeLine(s);
         }
      }catch(Exception e){
         throw new RuntimeException(e.getMessage(), e);
      }
   }
   default public void createWithDblQuot(OutputStream out, String charName){
      String lineSeparator = System.getProperty("line.separator");
      try(OutputStreamWriter writer = new OutputStreamWriter(out, charName)){
         for(String[] sary:getSupplier().get()){
            for(int i=0;i < sary.length;i++){
               sary[i] = sary[i]==null ? "" : sary[i];
            }
            writer.write(csvline(sary));
            writer.write(lineSeparator);
         }
      }catch(Exception e){
         throw new RuntimeException(e.getMessage(), e);
      }
   }
   default public String csvline(String[] ary){
      return "\"" + Arrays.stream(ary).map(s->s.replaceAll("\"","\"\"")).collect(Collectors.joining("\",\"")) + "\"";
   }
}

CSV出力データになる String[] のリスト

    List<String[]> list;

に対して

    CsvCreator c = ()->()->list;

で宣言して出力実行は、、、

try(OutputStream out = new FileOutputStream("sample.csv")){

   c.create(out, "MS932");

}catch(Exception e){
   e.printStackTrace();
}

で済んでしまう。

ダブルクォートで括る場合は、CsvCreator の createWithDblQuot を使う



Java 8 が出た時にこういうことは思いつくべきで、今更である。

新しい技術が出たらできるだけ早く新技術を使用する仕事環境に身を置かないと腕が鈍る。。。