指定された文字コードでCSVファイルを出力するjavaサンプル(エスケープ付)

CSVファイルの出力をjavaで行うサンプルです。

ただ、ひとくちにCSVの出力といっても、その要求は様々です。

基本的には、CSVですから、カンマで区切られたファイル形式なわけですが、データとデータの間を「”」(ダブルクォーテーション)で囲むかどうか、また、その場合、データの中にダブルクォーテーションが合った場合はエスケープ処理しないといけないですよね。

CSVファイル出力はいろんなプロジェクトで同じようなことを何度もやるのですが、そのたびにこういったことを考えてクラスを作成するのも手間なので、ここにおいておこうと思います。

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
 
public class CSVFileWriter {
     
    public static final String RETURN_CODE = "\r\n";
     
    /** エンコード utf8 */
    //public static final String CHAR_CODE = "UTF-8";
 
    /** エンコード ms932 */
    public static final String CHAR_CODE = "ms932";
 
    /** 出力ファイル */
    private File outputFile = null;
 
    /** OutputStream */
    private BufferedOutputStream out = null;
 
    /** 出力バイト数 */
    private int writeBytes = 0;
 
    /**
     * コンストラクタ
     * 
     * @param outputFile CSVファイル
     */
    public CSVFileWriter(final File outputFile) {
        this.outputFile = outputFile;
    }
 
    /**
     * ファイルをオープンし、ヘッダ行を読み取ります
     * 
     * @throws IOException 入出力例外
     */
    public final void open() throws IOException {
        close();
 
        out = new BufferedOutputStream(new FileOutputStream(outputFile));
    }
 
    /**
     * ファイルをクローズします.
     * 
     */
    public final void close() {
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                out = null;
            }
        }
        writeBytes = 0;
    }
 
     
    /**
     * エスケープ処理
     * 文字列全体を"(ダブルクォーテーション)で囲む
     * 
     * @param value カラム値
     * @return 処理後カラム値
     */
    private String escape(final String value) {
        if (value == null) {
            return """";
        }
         
        String ret = value.replaceAll(""", """");
        return """ + ret + """;
    }
 
    /**
     * ファイルの出力
     * 
     * @throws IOException ファイルの出力に失敗した場合
     */
    public void flush() throws IOException {
        out.flush();
    }
 
    /**
     * 出力バイト数の取得
     * 
     */
    public int getWriteBytes() {
        return writeBytes;
    }
     
     
    /**
     * ファイル出力処理
     * 
     * @param line 出力レコード
     * @throws IOException 入出力例外
     */
    public void writeLine(final List line) throws IOException {
        StringBuffer sb = new StringBuffer();
 
        boolean b = false;
        for (String s : line) {
            if (b) {
                sb.append(',');
            }
            sb.append(escape(s));
            b = true;
        }
        sb.append(RETURN_CODE);
        String p = sb.toString();
 
        byte[] bb = p.getBytes(CHAR_CODE);
         
        out.write(bb);
 
        writeBytes += bb.length;
    }
     
    /**
     * ファイル出力処理
     * 
     * @param line 出力レコード
     * @throws IOException 入出力例外
     */
    public void writeLineWithoutEscape(final List line) throws IOException {
        StringBuffer sb = new StringBuffer();
 
        boolean b = false;
        for (String s : line) {
            if (b) {
                sb.append(',');
            }
            sb.append(s);
            b = true;
        }
        sb.append(RETURN_CODE);
        String p = sb.toString();
 
        byte[] bb = p.getBytes(CHAR_CODE);
         
        out.write(bb);
 
        writeBytes += bb.length;
    }
 
}

これを使うときには、こんな感じで。

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
 
 
public class MainCSV {
 
    public static void main(String[] args) throws IOException{
 
 
        ArrayList<ArrayList> gLineList = new ArrayList<ArrayList>();
         
        ArrayList lineList = new ArrayList(); 
        lineList.add("col1");
        lineList.add("col2");
        lineList.add("col3");
        lineList.add("col4");
        gLineList.add(lineList);
         
        lineList = new ArrayList(); 
        lineList.add("val1");
        lineList.add("val2");
        //カンマがある場合
        lineList.add("val,3");
        //ダブルクォーテーションがある場合
        lineList.add("val"4");
        gLineList.add(lineList);
         
         
        CSVFileWriter writer = null;
                 
        try {
            File csvFile = new File("D:\MyDownload\out.csv");
             
            writer = new CSVFileWriter(csvFile);
            writer.open();
             
            Iterator<ArrayList> iter = gLineList.iterator();
            while(iter.hasNext()){
                writer.writeLine(iter.next());
            }
        }catch(Exception e){
            e.printStackTrace();
             
        } finally {
            // CSVファイルwriterのクローズ処理
            if (writer != null) {
                writer.close();
            }
 
        }
 
 
    }
 
}

writeLineメソッドを使えばこんな風に出力され、

writeLineWithoutEscapeメソッドを使えばこんな風に出力されます。