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

csv4j をラムダ式で。。。

CSVを読み込んで処理する csv4j の利用をラムダ式で書きたくなってきた。
ラムダ式の対象にしたいのは、CSVLineProcessor を使う CSVStreamProcessor である。

ラムダ式にしないこれまでの使用サンプル
try{
   CSVStreamProcessor csvStreamProcessor = new CSVStreamProcessor();
   csvStreamProcessor.processStream(new InputStreamReader(new FileInputStream("item.csv"), "UTF-8")
   , new CSVLineProcessor(){
      @Override
      public void processHeaderLine(int linenumer, List fields){
         // header Line
      }
      @Override
      public void processDataLine(int linenumber, List fields) {
         System.out.println("line " + linenumber + " : " + fields.get(3));
      }
      @Override
      public boolean continueProcessing() {
         return true;
      }
   });
}catch(Exception e){
   e.printStackTrace();
}


いろんな処理を埋め込めるので良いのだけど、いつもこんなに長く書くのがめんどうに感じてきた。

CSVLineProcessor を継承したCSVデータ行以外の処理を default にする。
CSVStreamProcessor を継承して、新しいprocessStream メソッドを用意する。
あまり良い名称が思いつかないので、"CSV" → "Csv" が付く名称にする。

import java.util.List;
import net.sf.csv4j.CSVLineProcessor;
/**
 * CsvLineProcessor
 */

@FunctionalInterface
public interface CsvLineProcessor extends CSVLineProcessor{
   @Override
   default public boolean continueProcessing(){
      return true;
   }
   @Override
   default public void processHeaderLine(int linenumber, List<String> fieldNames){
      processDataLine(linenumber, fieldNames);
   }
}


新しい、CsvStreamProcessor で、この CsvLineProcessor
を呼ぶ。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import net.sf.csv4j.CSVReader;
import net.sf.csv4j.CSVStreamProcessor;
import net.sf.csv4j.ParseException;
import net.sf.csv4j.ProcessingException;
/**
 * CsvStreamProcessor
 */

public class CsvStreamProcessor extends CSVStreamProcessor{
   public void processStream(InputStreamReader inReader, CsvLineProcessor processor) throws IOException, ProcessingException, ParseException{
      CSVReader reader = new CSVReader(new BufferedReader(inReader), getComment());
      try{
         int lineCount = 0;
         while(processor.continueProcessing()){
            List<String> fields = reader.readLine();
            if (fields.size()==0) break;
            try{
               if (isHasHeader() && lineCount==0){
                  processor.processHeaderLine(reader.getLineNumber(), fields);
               }else{
                  processor.processDataLine(reader.getLineNumber(), fields);
               }
            }catch(Exception e){
               throw new ProcessingException(e, reader.getLineNumber());
            }
            lineCount++;
         }
      }finally{
         reader.close();
      }
   }
}


ラムダ式で、以下のように書ける。。。

try{
   CsvStreamProcessor csvStreamProcessor = new CsvStreamProcessor();
   csvStreamProcessor.processStream(new InputStreamReader(new FileInputStream("item.csv"), "UTF-8")
   , (n, l)->{
      if (n==1){
         // header Line
      }else{
         System.out.println("line " + n + " : " + l.get(3));
      }
   }
);

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