1

銀行インターフェースのパーサーを継承しました。前の開発者は、実際にこれを非常に巧妙に行いました。銀行から入ってくるファイルは固定長フィールドです。彼がダウンロードからそのレコードを解析する方法は次のとおりです

    public static final String HEADER_RECORD_REGEX = "^(\\d{3})(\\d{12})(.{20})(\\d\\d)(\\d\\d)(\\d\\d)(\\d{12})(\\d\\d)$";

private static final int BANK_ID      = 1;
    private static final int ACCOUNT_ID   = 2;
    private static final int COMPANY_NAME = 3;
    private static final int MONTH              = 4;
    private static final int DAY                    = 5;
    private static final int YEAR                 = 6;
    private static final int SEQUENCE     = 7;
    private static final int TYPE_CODE      = 8;
    private static final int GROUP_COUNT  = TYPE_CODE;

if ( GROUP_COUNT == matcher.groupCount() )  {
            setBankId( matcher.group( BANK_ID ) );
            setAccountId( matcher.group( ACCOUNT_ID ) );
            setCompanyName( matcher.group( COMPANY_NAME ) );
            setProcessDate( matcher.group( MONTH ), matcher.group( DAY ),
                            matcher.group( YEAR ) );
            setSeqNumber( matcher.group( SEQUENCE ) );
            setTypeCode( matcher.group( TYPE_CODE ) );
        }

このプロセスを逆にして、テストできるように実際に銀行からモック ファイルを生成するという新しい要件があります。このメソッドを使用して、この同じ正規表現メソッドを使用してプロセスを逆にしてファイルを生成する方法はありますか、それとも標準パーサーの構築に戻るだけですか。

ありがとう

4

3 に答える 3

1

これは基本的にあなたが求めることをします。それがあなたのニーズに合うまであなたはそれで遊ぶことができます。

import java.util.*;

class Main
{
    public static String getLine(String bankID, String acctID, String companyName, String month, String day, String year, String seq, String typeCode)
    {
        return new Formatter()
               .format("%3.3s%12.12s%20.20s%2.2s%2.2s%2.2s%12.12s%2.2s", 
                       bankID, acctID, companyName, month,
                       day, year, seq, typeCode)
               .toString(); // 1 semicolon, technically a 1 liner.  aww yeah
    }

    public static void main(String[] args)
    {
        String tester = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        System.out.println(getLine(tester, tester, tester, tester,
                                   tester, tester, tester, tester));
    }
}

その例の出力は次のとおりです。

123123456789ABC123456789ABCDEFGHIJK121212123456789ABC12

これがイデオネです。

于 2012-11-08T21:32:58.430 に答える
0

逆にすることでオブジェクトをファイルに出力することを意味する場合、パーサーは必要なものではありません。必要なことは、同様の形式を使用して同じデータ メンバーをファイルに出力するメソッドを実装することだけです。正規表現にあるフィールド長で String.format を使用できます。いくつかのリファクタリングを行うことで、正規表現と文字列形式の間の共通点を抽出できますが、この正規表現はかなり単純であるため、これはやり過ぎだと考えるかもしれません。

于 2012-11-08T21:17:04.767 に答える
0

正規表現に制御されることから離れる必要があります。正規表現とフォーマッタを派生できる別の方法で構造を定義すると (以下を使用しenumます)、コードの拡張性が大幅に向上するだけでなく、そこからマーシャラーとアンマーシャラーを作成することもできます。 .

このようなものは良いスタートかもしれません:

public class BankRecords {
  static enum AccountField {
    BANK_ID("\\d", 3) {
      @Override
      void fill ( Account a, String s ) {
        a.bankId = s;
      }
    },
    ACCOUNT_ID("\\d", 12) {
      @Override
      void fill ( Account a, String s ) {
        a.accountID = s;
      }
    },
    COMPANY_NAME(".", 20) {
      @Override
      void fill ( Account a, String s ) {
        a.companyName = s;
      }
    },
    MONTH("\\d", 2) {
      @Override
      void fill ( Account a, String s ) {
        a.month = s;
      }
    },
    DAY("\\d", 2) {
      @Override
      void fill ( Account a, String s ) {
        a.day = s;
      }
    },
    YEAR("\\d", 2) {
      @Override
      void fill ( Account a, String s ) {
        a.year = s;
      }
    },
    SEQUENCE("\\d", 12) {
      @Override
      void fill ( Account a, String s ) {
        a.seqNumber = s;
      }
    },
    TYPE_CODE("\\d", 2) {
      @Override
      void fill ( Account a, String s ) {
        a.typeCode = s;
      }
    };
    // The type string in the regex.
    final String type;
    // How many characters.
    final int count;

    AccountField(String type, int count) {
      this.type = type;
      this.count = count;
    }

    // Each field can fill its part in the Account.
    abstract void fill ( Account a, String s );

    // My pattern.
    static Pattern pattern = Pattern.compile(asRegex());

    public static Account parse ( String record ) {
      Account account = new Account ();
      // Fire off the matcher with the regex and put each field in the Account object.
      Matcher matcher = pattern.matcher(record);
      for ( AccountField f : AccountField.values() ) {
        f.fill(account, matcher.group(f.ordinal() + 1));
      }
      return account;
    }

    public static String format ( Account account ) {
      StringBuilder s = new StringBuilder ();
      // Roll each field of the account into the string using the correct length from the enum.
      return s.toString();
    }

    private static String regex = null;

    static String asRegex() {
      // Only do this once.
      if (regex == null) {
        // Grow my regex from the field definitions.
        StringBuilder r = new StringBuilder("^");
        for (AccountField f : AccountField.values()) {
          r.append("(").append(f.type);
          // Special case count = 1 or 2.
          switch (f.count) {
            case 1:
              break;
            case 2:
              // Just one more.
              r.append(f.type);
              break;
            default:
              // More than that shoudl use the {} notation.
              r.append("{").append(f.count).append("}");
              break;
          }
          r.append(")");
        }
        // End of record.
        r.append("$");
        regex = r.toString();
      }
      return regex;
    }
  }

  public static class Account {
    String bankId;
    String accountID;
    String companyName;
    String month;
    String day;
    String year;
    String seqNumber;
    String typeCode;
  }
}

enumそれぞれが各フィールドの本質をどのようにカプセル化しているかに注目してください。タイプ、文字数、およびAccountオブジェクト内の場所。

于 2012-11-08T23:38:38.287 に答える