8. 固定長のカラムの読み書き

固定長のカラムは、書き込み時は任意の長さになるよう空白などを詰め、読み込み時は書き込み時に詰めた空白などの文字を除去するとで実現しています。[v2.1+]

固定長のカラムを定義したい場合は、フィールドにアノテーション @CsvFixedSize [ JavaDoc ] を付与します。

このアノテーションは、 以下の変換用のアノテーションを合成したアノテーションになります。

  • 読み込み時は、トリムするアノテーション @CsvOneSideTrim [ JavaDoc ]。

  • 書き込み時は、パディングするアノテーション @CsvMultiPad [ JavaDoc ]。

8.1. 基本的な設定

@CsvFixedSize の属性を指定することで、細やかな設定ができます。

  • 属性 size にて、固定長のサイズを指定します。

  • 属性 rightAlign で右寄せするかどうか指定します。

    • true のとき右寄せとなります。書き込み時に左側にパディング文字を詰め、読み見込み時に左側の文字をトリミングします。

    • false のとき左寄席で、デフォルト値となります。書き込み時に右側にパディング文字を詰め、読み見込み時に右側の文字をトリミングします。

  • 属性 padChar で、パディングする文字を指定できます。

    • デフォルトは半角空白です。

    • 値には、半角以外の全角文字の指定可能です。

  • 属性 chopped で、書き込み時に指定したサイズを超えている場合、切り出すか指定します。

    • デフォルトは true で切り出しません。

コード - 8.1.1 固定長カラムのBeanの定義例
 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.CsvFixedSize;
 4
 5
 6@CsvBean
 7public class SampleFixedSizeCsv {
 8
 9    // 右詰めする
10    @CsvColumn(number=1)
11    @CsvFixedSize(size=5, rightAlign=true)
12    private int id;
13
14    // パディング文字を全角空白にする。
15    // 全角を入力する前提としたカラムと想定し、さらに @CsvFullChar で半角を全角に変換します。
16    @CsvColumn(number=2, label="氏名")
17    @CsvFixedSize(size=10, padChar=' ')
18    @CsvFullChar
19    private String name;
20
21    // パディング文字をアンダースコア(_)にする。
22    @CsvColumn(number=3, label="生年月日")
23    @CsvFixedSize(length=10, padChar='_')
24    @CsvDateTimeFormat(pattern="uuuu-MM-dd")
25    private LocalDate birthday;
26
27    // 文字サイズを超えている場合は、切り出す。
28    @CsvColumn(number=4, label="備考")
29    @CsvFixedSize(size=20, chopped=true)
30    private String comment;
31
32    // getter, setterは省略
33}

8.2. 区切り文字のない固定長の処理

区切り文字のないCSVを処理する場合は、FixedSizeCsvPreference [ JavaDoc ] を使用し、CsvReader/CsvWriterを作成し処理します。 [v2.5+]

  • 全てのカラムに @CsvFixedSize を付与する必要があります。

  • 区切り文字のない固定長カラム読み込むには、FixedSizeCsvAnnotationBeanReader [ JavaDoc ] を使用します。

  • 区切り文字のない固定長カラムを書き込むには、FixedSizeCsvAnnotationBeanWriter [ JavaDoc ] を使用します。

コード - 8.2.1 区切り文字のない固定長CSVのサンプル
1   id氏名        生年月日______備考                  ⏎
2    1山田 太郎     1980-01-28全ての項目に値が設定。    ⏎
3    2田中 次郎     __________誕生日の項目が空。  ⏎
4    3鈴木 三郎     2000-03-25                    ⏎
コード - 8.2.2 区切り文字のない固定長カラムの読み込み
 1import java.io.IOException;
 2
 3import com.github.mygreen.supercsv.annotation.CsvBean;
 4import com.github.mygreen.supercsv.annotation.CsvColumn;
 5import com.github.mygreen.supercsv.annotation.CsvFixedSize;
 6import com.github.mygreen.supercsv.io.FixedSizeCsvAnnotationBeanReader;
 7import com.github.mygreen.supercsv.io.FixedSizeCsvPreference;
 8
 9public void testFixedSizeRead() throws IOException {
10
11    // FixedSizeCsvPreferenceの作成
12    FixedSizeCsvPreference<SampleFixedSizeCsv> csvPreference = FixedSizeCsvPreference.builder(SampleFixedSizeCsv.class)
13            .build();
14
15    // CsvReaderの作成
16    FixedSizeCsvAnnotationBeanReader<SampleFixedSizeCsv> csvReader = csvPreference.csvReader(
17            Files.newBufferedReader(Paths.get("sample_fixed_size.csv"), Charset.forName("UTF-8")));
18
19    try {
20        // 全行の取得
21        List<SampleFixedSizeCsv> list = csvReader.readAll();
22
23    } catch(SuperCsvException e) {
24        e.printStackTrace();
25    } finally {
26        csvReader.close();
27    }
28}
コード - 8.2.3 区切り文字のない固定長カラムの書き込み
 1import java.io.IOException;
 2
 3import com.github.mygreen.supercsv.annotation.CsvBean;
 4import com.github.mygreen.supercsv.annotation.CsvColumn;
 5import com.github.mygreen.supercsv.annotation.CsvFixedSize;
 6import com.github.mygreen.supercsv.io.FixedSizeCsvAnnotationBeanWriter;
 7import com.github.mygreen.supercsv.io.FixedSizeCsvPreference;
 8
 9public void testFixedSizeWrite() throws IOException {
10
11    // FixedSizeCsvPreferenceの作成
12    FixedSizeCsvPreference<SampleFixedSizeCsv> csvPreference = FixedSizeCsvPreference.builder(SampleFixedSizeCsv.class)
13            .build();
14
15    // CsvWriterの作成
16    FixedSizeCsvAnnotationBeanWriter<SampleFixedColumnBean> csvWriter = csvPrefrerence.csvWriter(
17            Files.newBufferedWriter(Paths.get("sample_fixed_size.csv"), Charset.forName("UTF-8")));
18
19    // 書き込みデータを作成
20    List<SampleFixedColumnBean> list = new ArrayList<>();
21    list.add(...);
22
23    try {
24        // 全行の書き込み
25        csvWriter.writeAll(list);
26    } catch (SuperCsvException e) {
27        e.printStackTrace();
28    } finally {
29        csvWriter.close();
30    }
31}

8.3. 区切り文字のある固定長の処理

区切り文字のある固定長CSVを処理する場合は、固定長としたいカラムにのみ @CsvFixedSize を付与し、通常のCsvAnnotationBeanReader / CsvAnnotationBeanWriter を使用します。

コード - 8.3.1 区切り文字のある固定長CSVのサンプル
1   id,氏名        ,生年月日______,備考                  ⏎
2    1,山田 太郎     ,1980-01-28,全ての項目に値が設定。    ⏎
3    2,田中 次郎     ,__________,誕生日の項目が空。  ⏎
4    3,鈴木 三郎     ,2000-03-25,                    ⏎
コード - 8.3.2 区切り文字のある固定長カラムの読み込み
 1import java.io.IOException;
 2
 3import com.github.mygreen.supercsv.annotation.CsvBean;
 4import com.github.mygreen.supercsv.annotation.CsvColumn;
 5import com.github.mygreen.supercsv.annotation.CsvFixedSize;
 6import com.github.mygreen.supercsv.io.FixedSizeCsvAnnotationBeanReader;
 7import com.github.mygreen.supercsv.io.FixedSizeCsvPreference;
 8
 9public void testFixedSizeRead2() throws IOException {
10
11    // CsvReaderの作成
12    CsvAnnotationBeanReader<SampleFixedSizeCsv> csvWriter = new CsvAnnotationBeanReader<>(
13            SampleFixedSizeCsv.class,
14            Files.newBufferedReader(Paths.get("sample_fixed_size.csv"), Charset.forName("UTF-8")),
15            CsvPreference.STANDARD_PREFERENCE);
16
17    try {
18        // 全行の取得
19        List<SampleFixedSizeCsv> list = csvReader.readAll();
20
21    } catch(SuperCsvException e) {
22        e.printStackTrace();
23    } finally {
24        csvReader.close();
25    }
26}
コード - 8.3.3 区切り文字のある固定長カラムの書き込み
 1import java.io.IOException;
 2
 3import com.github.mygreen.supercsv.annotation.CsvBean;
 4import com.github.mygreen.supercsv.annotation.CsvColumn;
 5import com.github.mygreen.supercsv.annotation.CsvFixedSize;
 6import com.github.mygreen.supercsv.io.FixedSizeCsvAnnotationBeanWriter;
 7import com.github.mygreen.supercsv.io.FixedSizeCsvPreference;
 8
 9public void testFixedSizeWrite2() throws IOException {
10
11    // CsvReaderの作成
12    CsvAnnotationBeanWriter<SampleFixedSizeCsv> csvWriter = new CsvAnnotationBeanWriter<>(
13            SampleFixedSizeCsv.class,
14            Files.newBufferedWriter(Paths.get("sample_fixed_size.csv"), Charset.forName("UTF-8")),
15            CsvPreference.STANDARD_PREFERENCE);
16
17    // 書き込みデータを作成
18    List<SampleFixedColumnBean> list = new ArrayList<>();
19    list.add(...);
20
21    try {
22        // 全行の書き込み
23        csvWriter.writeAll(list);
24    } catch (SuperCsvException e) {
25        e.printStackTrace();
26    } finally {
27        csvWriter.close();
28    }
29}

出力されるCSVは下記のようになります。

ヘッダー行が固定長になっていないことがわかります。

コード - 8.3.4 出力されるCSV(1)
1id,氏名,生年月日,備考
2         1,山田 太郎     ,1990-01-12,コメント
3         2,山田 花子     ,__________,

ヘッダー行もカラムの定義と同様に固定長にしたい場合は、@CsvBean(headerMapper=<ヘッダーのマッピング処理クラス>) でヘッダーの処理方法を変更します。

FixedSizeHeaderMapper [ JavaDoc ] は、フィールドに付与されたアノテーション @CsvFixedSize を元に、見出しに対してパディングを行います。

コード - 8.3.5 ヘッダーのマッピング定義を変更する
 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.CsvFixedSize;
 4import com.github.mygreen.supercsv.builder.FixedSizeHeaderMapper;
 5
 6@CsvBean(header=true, headerMapper=FixedSizeHeaderMapper.class)
 7public class SampleFixedSizeCsv {
 8
 9    // 右詰めする
10    @CsvColumn(number=1)
11    @CsvFixedSize(size=10, rightAlign=true)
12    private int id;
13
14    // 以下、省略
15}
コード - 8.3.6 出力されるCSV - ヘッダーも固定長にする
1        id,氏名        ,生年月日__,備考
2         1,山田 太郎     ,1990-01-12,コメント
3         2,山田 花子     ,__________,

注釈

ヘッダーの見出しが全角、実際の値が半角で出力するような場合、意図した変換がされない場合があります。 その際は、独自に com.github.mygreen.supercsv.builder.HeaderMapper を実装したクラスを指定することで対応できます。

8.4. パディング処理方式の切り替え

固定長としてパディングする場合、サイズカウント方法の考え方は、複数あります。 例えば、半角は1文字、全角は2文字分として換算する。 または、文字のバイト数で換算することもあります。

  • パディング処理の実装を切り替えることができ、@CsvFixedSize の属性 paddingProcessor でパディング処理の実装クラスを指定します。

  • 本ライブラリでは、以下のパディング処理の実装が提供されています。

    • SimplePaddingProcessor [ JavaDoc ] - 文字の種別にかかわらず1文字としてカウントしてパディングします。

    • CharWidthPaddingProcessor [ JavaDoc ] - 文字の幅(半角は1文字、全角は2文字)によってカウントしてパディングします。デフォルトの実装です。

    • ByteSizePaddingProcessor [ JavaDoc ] - バイト数によってカウントしてパディングします。

      • バイト数で換算する場合、文字コードに依存するため、文字コードに対応したサブクラスを指定する必要があります。

  • 独自のパディング処理を指定したい場合は、 com.github.mygreen.supercsv.cellprocessor.conversion.PaddingProcessor を実装したクラスを指定してください。

コード - 8.4.1 ヘッダーのマッピング定義を変更する
 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3import com.github.mygreen.supercsv.annotation.CsvFixedSize;
 4import com.github.mygreen.supercsv.builder.FixedSizeHeaderMapper;
 5import com.github.mygreen.supercsv.cellprocessor.conversion.ByteSizePaddingProcessor;
 6import com.github.mygreen.supercsv.cellprocessor.conversion.CharWidthPaddingProcessor;
 7import com.github.mygreen.supercsv.cellprocessor.conversion.SimplePaddingProcessor;
 8
 9@CsvBean(header=true)
10public class SampleFixedSizeCsv {
11
12    // 文字の種別にかかわらず1文字としてカウントしてパディングします。
13    @CsvColumn(number=1)
14    @CsvFixedSize(size=10, paddingProcessor=SimplePaddingProcessor.class)
15    private int id;
16
17    // 文字の幅(半角は1文字、全角は2文字)によってカウントしてパディングします。
18    @CsvColumn(number=2)
19    @CsvFixedSize(size=20, paddingProcessor=CharWidthPaddingProcessor.class)
20    private String name;
21
22    // バイト数によってカウントしてパディングします。
23    @CsvColumn(number=3)
24    @CsvFixedSize(size=20, paddingProcessor=ByteSizePaddingProcessor.Windows31j.class)
25    private String comment;
26
27    // 以下、省略
28}