CB3 - チュートリアル 第3章 - 3.6固定長ファイルアクセス - その2

 3.6.1概要

  • このサンプルの目的
     このアプリケーション作成例を通して、以下について知ることができます。
    • 固定長ファイル(ライタ、リーダ)設定ファイルでの詳細なフォーマット形式の使用方法
    • 独自のフォーマットクラスを作成してレコードの項目をフォーマットする方法

  • サンプルアプリケーションの内容
     固定長ファイルへの書込み、読込みを行い読み込み結果を標準出力へ表示するバッチアプリケーションです。  
     サンプルアプリケーションの概要を下図に示します。
     
     
     「3.5固定長ファイルアクセス - その1」では固定長ファイルの書込み時での簡単なフォーマットについて紹介しました。 フォーマットは固定長ファイルリーダ設定ファイルにも指定することが可能です。 この場合は、固定長ファイルからの読込み時にその形式に沿った内容で解析し、値を取得します。 また、空白文字や0などの任意の文字を左詰や右詰に指定することができます。
     CB3ではデフォルトでDecimalFormatやSimpleDateFormatを利用してフォーマットを行いますが、 独自で作成したフォーマットクラスをレコード項目のフォーマットに適用することができます。
     
     このサンプルでは以下のファイルについて説明します。  
    • FixedLengthSample2.java
       サービスのプログラムです。上図内の赤枠の部分に相当します。
    • FixedWriteFormatter.java
       ファイルレコードライタの独自フォーマットクラスです。上図内のライタフォーマットに相当します。
    • FixedReadFormatter.java
       ファイルレコードリーダの独自フォーマットクラスです。上図内のリーダフォーマットに相当します。
    • writerConfig2.xml
       固定長ファイルの項目の長さや型などのフォーマットを記述した設定ファイルです。
       上図内の固定長ファイルライタ設定ファイルに相当します。
    • readerConfig2.xml
       固定長ファイルの項目の長さや型などのフォーマットを記述した設定ファイルです。
       上図内の固定長ファイルリーダ設定ファイルに相当します。
    • applicationContext.xml
       CB3がserviceContext.xmlなどのspringフレームワーク関連の設定ファイルを読み込むための起点となる コンテキストファイルです。
      このファイルは内容が「3.5固定長ファイルアクセス - その1」と同じため省略します。
    • serviceContext.xml
       実行対象のサービスを定義します。
    • 起動用バッチファイル - fixedlength2.bat
       サービスを起動するためのバッチファイルです。
    • fixedtest2.txt
       書込み読込み対象のファイルです。

 3.6.2サービスの作成

  • FixedLengthSample2.java

     01:public class FixedLengthSample2 extends CB3Service {
     02:    private static final String FILE_PATH = "fixedtest2.txt";
     03:    @Override
     04:    protected int doService(ServiceParameters serviceparameters,
     05:            RuntimeParameters runtimeparameters) throws ServiceException {
     06:        fileWrite();
     07:        fileRead();
     08:        return 0;
     09:    }
     10:
     11:    /**
     12:     * ファイルへの書き込みを行う
     13:     */
     14:    private void fileWrite(){
     15:        FlatFileRecordWriter writer =
                     (FlatFileRecordWriter)getDataAccessContext().lookup("writerConfig2");
     16:        // ファイルオープン
     17:        writer.open(FILE_PATH);
     18:
     19:        // 追加するデータを設定する
     20:        HashMap<String, String> data = new HashMap<String, String>();
     21:        data.put("name","tanaka");
     22:        data.put("staffId","11");
     23:        data.put("staffSubId","12");
     24:        // dateの場合はデフォルトの形で設定を行う yyyy/MM/dd HH:mm:ss
     25:        data.put("registrationDate","2008/01/01 00:00:00");
     26:
     27:        // 一行分のデータを追加したレコードを生成する
     28:        FlatFileRecord record = writer.createFlatFileRecord(data);
     29:
     30:        // ファイルへの書き込む
     31:        writer.write(record);
     32:
     33:        // ファイルクローズ
     34:        writer.close();
     35:    }
     36:
     37:    /**
     38:     * ファイルの読み込みを行う
     39:     */
     40:    private void fileRead(){
     41:        FlatFileRecordReader reader =
                     (FlatFileRecordReader)getDataAccessContext().lookup("readerConfig2");
     42:        // 読み込むファイルをオープン
     43:        reader.open(FILE_PATH);
     44:
     45:        FlatFileRecord record = null;
     46:        System.out.println("読み込み結果:" + FILE_PATH);
     47:
     48:        while((record = reader.nextRecord()) != null ){
     49:            System.out.println("name:" + record.getString("name"));
     50:            System.out.println("staffId:" + record.getString("staffId"));
     51:            System.out.println("staffSubId:" + record.getString("staffSubId"));
     52:            System.out.println("registrationDate:" + record.getString("registrationDate"));
     53:        }
     54:    }
     55:}
    

    このサンプルはファイルへの書込み処理(14行目:fileWrite())を行った後、書込んだファイルの読込み(40行目:fileRead())処理を行っています。

    ■書込み処理
    20行目〜25行目:
    各項目にデータの設定を行っています。各項目のデータの定義は固定長ファイルライタ設定ファイル(writerConfig2.xml)で行います。このサンプル での定義内容は次のようになっています。
    <field name="name" length="6"/>
    
    21行目のデータ設定処理に対応します。「3.5固定長ファイルアクセス - その1」と同じです。
    <field name="staffId" length="10" align="left" padding="0"/>
    
    22行目のデータ設定処理に対応します。align属性はデータの右寄せ左寄せの指定を行います。leftまたはrightを指定することができます。 padding属性は文字埋めの指定を行うことができます。この上記例では0埋めの指定を行っています。
    <field name="staffSubId" length="10" patternClass="jp.co.cybec.cb3.sample.file.fixed.FixedWriteFormatter"
                  type="number" pattern="0000000000" align="right" padding="0"/>
    
    23行目のデータ設定処理に対応します。
    この例ではpatternClass属性を使用しています。patternClass属性を使うことで、独自のフォーマット処理クラスを作成することができます。
    作成例を以下に示します。

     01:public class FixedWriteFormatter implements RecordFieldWriterFormatable {
     02:    /**
     03:     * フォーマットを行う - 初めに呼び出される
     04:     */
     05:    public String format(String pattern, String type, String data)
     06:            throws DataFormatException {
     07:        System.out.println("called format method");
     08:        System.out.println("pattern:" + pattern + " type:" + type + " data:" + data);
     09:        System.out.println("");
     10:
     11:        DecimalFormat df = new DecimalFormat();
     12:        df.applyPattern(pattern);
     13:
     14:        return  df.format(new BigDecimal(data));
     15:    }
     16:
     17:    /**
     18:     * パディングを行う - formatメソッドの次に呼び出される
     19:     */
     20:    public String padding(String length, String algin, String padding, String data)
     21:            throws DataFormatException {
     22:        System.out.println("called padding method");
     23:        System.out.println("length:" + length + " algin:" + algin + " padding:" + padding +
                                    " data:" + data);
     24:        System.out.println("");
     25:
     26:        return data;
     27:    }
     28:}
    

    独自フォーマットクラスを作成するにはRecordFieldWriterFormatableインターフェイスを実装します。このインターフェイスには format()メソッドとpadding()メソッドが定義され、format()⇒padding()の順で呼び出されます。各メソッドは次のような引数をとります。
     String format(String pattern, String type, String data) throws DataFormatException;
     String padding(String length, String algin, String padding, String data) throws DataFormatException;
    それぞれのメソッドの引数から、設定ファイルの値を取得することができます。戻り値は編集後のデータを戻り値として返します。

    <field name="registrationDate" length="10" type="date" pattern="yyyy/MM/dd"/>
    
    25行目のデータ設定処理に対応します。

    ■読込み処理
    49行目〜52行目:
    ファイルレコードリーダからデータ1行分のレコードオブジェクトを取得し、読込みデータの取得を行っています。読込みデータの定義は 固定長ファイルリーダ設定ファイル(readerConfig2.xml)で行います。このサンプルでの定義内容は次のようになっています。
    <field name="name" length="6"/>
    
    49行目のデータ取得処理に対応しています。length属性で読み込むデータの長さを指定します。
    <field name="staffId" length="10" align="left" padding="0"/>
    
    50行目のデータ取得処理に対応しています。length属性で読み込むデータの長さを指定します。align属性は書込みの場合と同様に右寄せ左寄せの 指定を行います。padding属性は書込み処理と違い、読み込んだデータを指定された文字でトリムします。
    <field name="staffSubId" length="10" patternClass="jp.co.cybec.cb3.sample.file.fixed.FixedReadFormatter"
                 type="number" pattern="0000000000" align="right" padding="0"/>
    
    51行目のデータ取得処理に対応しています。ここでも書込み処理と同様にpatternClassを指定しています。読込み処理の場合も 独自のフォーマット処理クラスを作成することができます。
    作成例を以下に示します。

     01:public class FixedReadFormatter implements RecordFieldReaderFormatable {
     02:
     03:    /**
     04:     * トリム処理を行うメソッド - 初めに呼び出される
     05:     */
     06:    public String trim(String algin, String padding, String data)
     07:            throws DataFormatException {
     08:        System.out.println("called trim method");
     09:        System.out.println("algin:" + algin + " padding:" + padding + " data:" + data);
     10:        System.out.println("");
     11:
     12:        return data.trim();
     13:    }
     14:
     15:    /**
     16:     * フォーマットメソッド - trimメソッドの次に呼び出される
     17:     */
     18:    public String format(String pattern, String type, String data)
     19:            throws DataFormatException {
     20:        System.out.println("called format method");
     21:        System.out.println("pattern:" + pattern + " type:" + type + " data:" + data);
     22:        System.out.println("");
     23:
     24:        return data;
     25:    }
     26:}
    

    独自フォーマットクラスを作成するにはRecordFieldReaderFormatableインターフェイスを実装します。このインターフェイスには trim()メソッドとformat()メソッドが定義され、trim()⇒format()の順で呼び出されます。各メソッドは次のような引数をとります。
     String trim(String algin, String padding, String data) throws DataFormatException;
     String format(String pattern, String type, String data) throws DataFormatException;
    それぞれのメソッドの引数から、設定ファイルの値を取得することができます。戻り値は編集後のデータを戻り値として返します。

    <field name="registrationDate" length="10"/>
    
    FixedLengthSample2.javaの52行目に対応します。

 3.6.3設定ファイルの作成

  • writerConfig2.xml
    固定長ファイルライタの設定ファイルです。

     01:<?xml version="1.0" encoding="UTF-8"?>
     02:<flatfile-writer  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     03:  xsi:noNamespaceSchemaLocation="FixedLengthRecordWriterConfig.xsd">
     04:  <append>false</append>
     05:  <format>
     06:    <fields>
     07:      <field name="name" length="6"/>
     08:
     09:      <field name="staffId" length="10" align="left" padding="0"/>
     10:
     11:      <field name="staffSubId" length="10"
                       patternClass="jp.co.cybec.cb3.sample.file.fixed.FixedWriteFormatter"
     12:              type="number" pattern="0000000000" align="right" padding="0"/>
     13:
     14:      <field name="registrationDate" length="10" type="date" pattern="yyyy/MM/dd"/>
     15:    </fields>
     16:  </format>
     17:</flatfile-writer>
    

    9行目:
    「3.6.2サービスの作成」で説明したalign属性とpadding属性を設定しています。
    align属性はデータの右寄せ左寄せの指定を行います。leftまたはrightを指定することができます。 padding属性は文字埋めの指定を行うことができます。この上記例では0埋めの指定を行っています。

    11行目:
    「3.6.2サービスの作成」で説明したpatternClass属性の設定をおこなっています。詳細は「3.6.2サービスの作成」を参照してください。

  • readerConfig2.xml
    固定長ファイルリーダの設定ファイルです。

     01:<?xml version="1.0" encoding="UTF-8"?>
     02:<flatfile-reader  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     03:  xsi:noNamespaceSchemaLocation="FixedLengthRecordReaderConfig.xsd">
     04:  <format>
     05:    <fields>
     06:      <field name="name" length="6"/>
     07:
     08:      <field name="staffId" length="10" align="left" padding="0"/>
     09:
     10:      <field name="staffSubId" length="10"
                      patternClass="jp.co.cybec.cb3.sample.file.fixed.FixedReadFormatter"
     11:             type="number" pattern="0000000000" align="right" padding="0"/>
     12:
     13:      <field name="registrationDate" length="10"/>
     14:    </fields>
     15:  </format>
     16:</flatfile-reader>
    

    8行目:
    「3.6.2サービスの作成」で説明したalign属性とpadding属性を設定しています。
    align属性はデータの右寄せ左寄せの指定を行います。leftまたはrightを指定することができます。 padding属性は書込み処理と違い、読み込んだデータを指定された文字でトリムします。この上記例では文字「0」をトリムします。

    10行目:
    「3.6.2サービスの作成」で説明したpatternClass属性の設定をおこなっています。詳細は「3.6.2サービスの作成」を参照してください。

  • serviceContext.xml
    このサンプルの実行に必要となるサービスのコンテキストファイルです。

     01:<?xml version="1.0" encoding="UTF-8"?>
     02:    <!-- 途中省略-->
     03:
     04:    <!-- ServiceProvider -->
     05:    <bean id="fixed2" class="jp.co.cybec.cb3.container.provider.ServiceProviderImpl">
     06:        <property name="service"><ref bean="sample2"/></property>
     07:    </bean>
     08:    <!-- Service -->
     09:    <bean id="sample2" class="jp.co.cybec.cb3.sample.file.fixed.FixedLengthSample2">
     10:        <property name="dataAccessContext"><ref bean="accessContext2"/></property>
     11:    </bean>
     12:
     13:    <!-- 途中省略-->
     14:
     15:    <!-- DataAccessContext -->
     16:    <bean id="accessContext2" class="jp.co.cybec.cb3.accessor.DataAccessContextImpl">
     17:        <constructor-arg index="0"><ref bean="testDataAccessors2"/></constructor-arg>
     18:    </bean>
     19:    <util:map id="testDataAccessors2">
     20:        <!-- アクセス用設定ファイル -->
     21:        <entry key="readerConfig2"><ref bean="fixedLengthRecordReader"/></entry>
     22:        <entry key="writerConfig2"><ref bean="fixedLengthRecordWriter"/></entry>
     23:    </util:map>
     24:</beans>
    

    「3.5固定長ファイルアクセス - その1」で紹介した内容とほとんど変わりはありません。
    21〜22行目で固定長ファイルアクセッサの設定を行っています。

 3.6.4サービスの実行

  • fixedlength2.bat
     01:@echo off
     02:
     03:setlocal
     04:
     05:call ./set_classpath_com.bat
     06:
     07:set CLASSPATH=%CB3_HOME%/resources/config/fixed;%CLASSPATH%
     08:
     09:java jp.co.cybec.cb3.container.provider.ServiceProviderImpl -ServiceName fixed2
     10:
     11:pause
    

    上記バッチファイルを実行すると下記のように表示されます。

    called format method
    pattern:0000000000 type:number data:12
    
    called padding method
    length:10 algin:right padding:0 data:0000000012
    
    読み込み結果:fixedtest2.txt
    called trim method
    algin:right padding:0 data:0000000012
    
    called format method
    pattern:0000000000 type:number data:0000000012
    
    name:tanaka
    staffId:11
    staffSubId:0000000012
    registrationDate:2008/01/01
    続行するには何かキーを押してください . . .
    

    fixedtest2.txt確認すると以下のようにデータが登録されています。