15

Javaで固定長のフラットファイルを作成するのに役立つフレームワーク/ライブラリはありますか?

変換、パディング、配置、フィラーなどを気にせずに、Bean/エンティティのコレクションをフラットファイルに書き込みたい

たとえば、次のようなBeanを解析したいと思います。

public class Entity{
    String name = "name"; // length = 10; align left; fill with spaces
    Integer id = 123; // length = 5; align left; fill with spaces
    Integer serial = 321 // length = 5; align to right; fill with '0'
    Date register = new Date();// length = 8; convert to yyyyMMdd
}

... の中へ ...

name      123  0032120110505
mikhas    5000 0122120110504
superuser 1    0000120101231

..。

4

9 に答える 9

12

それでもフレームワークを探している場合は、http://www.beanio.orgでBeanIOをチェックしてください。

于 2011-08-04T17:27:08.587 に答える
12

「レガシー」システムのフォーマットに対応できるフレームワークに遭遇する可能性はほとんどありません。ほとんどの場合、レガシーシステムは標準フォーマットを使用しませんが、フレームワークはそれらを期待します。レガシーCOBOLシステムとJava/Groovy変換の保守者として、私はこの不一致に頻繁に遭遇します。「変換、パディング、配置、フィラーなどの心配」は、主にレガシーシステムを扱うときに行うことです。もちろん、その一部を便利なヘルパーにカプセル化することもできます。しかし、ほとんどの場合、java.util.Formatterに精通する必要があります。

たとえば、デコレータパターンを使用して、変換を行うデコレータを作成できます。以下は少しグルーヴィーです(Javaに簡単に変換できます):

class Entity{
    String name = "name"; // length = 10; align left; fill with spaces
    Integer id = 123; // length = 5; align left; fill with spaces
    Integer serial = 321 // length = 5; align to right; fill with '0'
    Date register = new Date();// length = 8; convert to yyyyMMdd
}

class EntityLegacyDecorator {
     Entity d
     EntityLegacyDecorator(Entity d) { this.d = d }

     String asRecord() {
         return String.format('%-10s%-5d%05d%tY%<tm%<td',
                               d.name,d.id,d.serial,d.register)
   }
 }

def e = new Entity(name: 'name', id: 123, serial: 321, register: new Date('2011/05/06'))

assert new EntityLegacyDecorator(e).asRecord() == 'name      123  0032120110506'

これは、これらの数が多すぎず、オブジェクトが複雑すぎない場合に機能します。しかし、すぐにフォーマット文字列が耐えられなくなります。次に、次のようなDateのデコレータが必要になる場合があります。

class DateYMD {
     Date d
     DateYMD(d) { this.d = d }
     String toString() { return d.format('yyyyMMdd') }
 }

したがって、%sでフォーマットできます。

    String asRecord() {
         return String.format('%-10s%-5d%05d%s',
                               d.name,d.id,d.serial,new DateYMD(d.register))
   }

ただし、かなりの数のBeanプロパティの場合、文字列はまだ粗すぎるため、渡されたCOBOL仕様のように見える列と長さを理解するものが必要なので、次のように記述します。

 class RecordBuilder {

    final StringBuilder record 

    RecordBuilder(recordSize) {
        record = new StringBuilder(recordSize)
        record.setLength(recordSize)
     }

    def setField(pos,length,String s) { 
       record.replace(pos - 1, pos + length, s.padRight(length))
    }

    def setField(pos,length,Date d) { 
      setField(pos,length, new DateYMD(d).toString())
    }

   def setField(pos,length, Integer i, boolean padded) { 
       if (padded) 
          setField(pos,length, String.format("%0" + length + "d",i))
       else 
          setField(pos,length, String.format("%-" + length + "d",i))
    }

    String toString() { record.toString() }
}

class EntityLegacyDecorator {

     Entity d

     EntityLegacyDecorator(Entity d) { this.d = d }

     String asRecord() {
         RecordBuilder record = new RecordBuilder(28)
         record.setField(1,10,d.name)
         record.setField(11,5,d.id,false)
         record.setField(16,5,d.serial,true)
         record.setField(21,8,d.register)
         return record.toString()
     }

}

レガシーシステムを処理するのに十分なsetField()メソッドを作成したら、それを「フレームワーク」としてGitHubに投稿することを簡単に検討します。これにより、次の貧弱な樹液が再びそれを行う必要がなくなります。しかし、次に、COBOLが「日付」(MMDDYY、YYMMDD、YYDDD、YYYYDDD)と数値(10進数、明示的な小数点、末尾の小数点としての符号、または先頭の浮動小数点文字としての符号)を格納するのを見たすべてのばかげた方法を検討します。次に、このための優れたフレームワークを誰も作成していない理由を理解し、例として、作成コードの一部をSOに投稿することがあります...;)

于 2011-05-05T22:01:30.307 に答える
2

uniVocityパーサーは、さまざまなフィールドやパディングなどの行を含む、トリッキーな固定幅フォーマットをサポートするのに大いに役立ちます。

この例をチェックして、架空のクライアントとアカウントの詳細を記述してください。これは、先読み値を使用して、行を書き込むときに使用する形式を識別します。

    FixedWidthFields accountFields = new FixedWidthFields();
    accountFields.addField("ID", 10); //account ID has length of 10
    accountFields.addField("Bank", 8); //bank name has length of 8
    accountFields.addField("AccountNumber", 15); //etc
    accountFields.addField("Swift", 12);

    //Format for clients' records
    FixedWidthFields clientFields = new FixedWidthFields();
    clientFields.addField("Lookahead", 5); //clients have their lookahead in a separate column
    clientFields.addField("ClientID", 15, FieldAlignment.RIGHT, '0'); //let's pad client ID's with leading zeroes.
    clientFields.addField("Name", 20);

    FixedWidthWriterSettings settings = new FixedWidthWriterSettings();
    settings.getFormat().setLineSeparator("\n");
    settings.getFormat().setPadding('_');

    //If a record starts with C#, it's a client record, so we associate "C#" with the client format.
    settings.addFormatForLookahead("C#", clientFields);

    //Rows starting with #A should be written using the account format
    settings.addFormatForLookahead("A#", accountFields);

    StringWriter out = new StringWriter();

    //Let's write
    FixedWidthWriter writer = new FixedWidthWriter(out, settings);

    writer.writeRow(new Object[]{"C#",23234, "Miss Foo"});
    writer.writeRow(new Object[]{"A#23234", "HSBC", "123433-000", "HSBCAUS"});
    writer.writeRow(new Object[]{"A#234", "HSBC", "222343-130", "HSBCCAD"});
    writer.writeRow(new Object[]{"C#",322, "Mr Bar"});
    writer.writeRow(new Object[]{"A#1234", "CITI", "213343-130", "CITICAD"});

    writer.close();

    System.out.println(out.toString());

出力は次のようになります。

C#___000000000023234Miss Foo____________
A#23234___HSBC____123433-000_____HSBCAUS_____
A#234_____HSBC____222343-130_____HSBCCAD_____
C#___000000000000322Mr Bar______________
A#1234____CITI____213343-130_____CITICAD_____

これは大まかな例です。注釈付きJavaBeanのサポートなど、利用可能な他の多くのオプションがあります。これらはここにあります。

開示:私はこのライブラリの作成者です。オープンソースで無料です(Apache 2.0ライセンス)

于 2016-05-02T03:40:41.803 に答える
1

Spring BatchにはがありFlatFileItemWriterますが、SpringBatchAPI全体を使用しない限り役に立ちません。


しかし、それとは別に、ファイルへの書き込みを簡単にするライブラリが必要だと思います(IOコード全体を自分で記述したい場合を除く)。

頭に浮かぶ2つは次のとおりです。

グアバ

Files.write(stringData, file, Charsets.UTF_8);

Commons / IO

FileUtils.writeStringToFile(file, stringData, "UTF-8");
于 2011-05-04T14:35:27.820 に答える
1

ライブラリFixedformat4jは、まさにこれを行うための非常に優れたツールです:http: //fixedformat4j.ancientprogramming.com/

于 2013-08-15T09:24:45.273 に答える
0

フレームワークについてはわかりませんが、RandomAccessFileを使用できます。ファイルポインタをファイル内の任意の場所に配置して、読み取りと書き込みを行うことができます。

于 2011-05-04T14:35:32.157 に答える
0

使用している素敵なライブラリを見つけました:
http ://sourceforge.net/apps/trac/ffpojo/wiki

XMLまたは注釈を使用して構成するのは非常に簡単です!

于 2011-05-06T12:39:09.153 に答える
-1

Bean /エンティティをフラットファイルに書き込む簡単な方法は、ObjectOutputStreamを使用することです。

public static void writeToFile(File file, Serializable object) throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
    oos.writeObject(object);
    oos.close();
}

固定長フラットファイルに書き込むことができます

FileUtils.writeByteArrayToFile(new File(filename), new byte[length]);

ファイルをどのように処理するかについて、より具体的にする必要があります。;)

于 2011-05-04T14:40:38.227 に答える
-1

FFPOJO APIを試してみてください。固定長のフラットファイルを作成するために必要なものがすべて揃っており、ファイルをオブジェクトに、またはその逆に変換します。

@PositionalRecord
public class CFTimeStamp {

    String timeStamp;

    public CFTimeStamp(String timeStamp) {
        this.timeStamp = timeStamp;
    }

    @PositionalField(initialPosition = 1, finalPosition = 26, paddingAlign = PaddingAlign.RIGHT, paddingCharacter = '0')
    public String getTimeStamp() {
        return timeStamp;
    }

    @Override
    public String toString() {
        try {
            FFPojoHelper ffPojo = FFPojoHelper.getInstance();
            return ffPojo.parseToText(this);
        } catch (FFPojoException ex) {
            trsLogger.error(ex.getMessage(), ex);
        }
        return null;
    }
}
于 2016-08-29T15:16:42.813 に答える