【问题标题】:Parsing multi-line fixed-width files解析多行定宽文件
【发布时间】:2011-04-12 21:14:55
【问题描述】:

我有一个固定宽度的平面文件。更糟糕的是,每一行可以是新记录,也可以是上一行的子记录,由每行的第一个字符标识:

A0020SOME DESCRIPTION   MORE DESCRIPTION 922 2321      # Separate
A0021ANOTHER DESCRIPTIONMORE DESCRIPTION 23111442      # records
B0021ANOTHER DESCRIPTION   THIS TIME IN ANOTHER FORMAT # sub-record of record "0021"

我尝试过使用Flatworm,它似乎是一个用于解析固定宽度数据的优秀库。不幸的是,它的文档指出:

"Repeating segments are supported only for delimited files"

(同上,“重复片段”)。

我宁愿不为此编写自定义解析器。是否可以 (1) 在 Flatworm 中执行此操作,或者 (2) 是否有提供此类(多行、多子记录)功能的库?

【问题讨论】:

    标签: java flat-file fixed-width


    【解决方案1】:

    你看过 JRecordBind 吗?

    http://jrecordbind.org/

    “JRecordBind 支持分层固定长度文件:某些类型的记录是其他记录类型的“儿子”。”

    【讨论】:

      【解决方案2】:

      检查Preon。尽管 Preon 的目标是比特流压缩数据,但您也许可以扭转它的手臂并将其用于您确定的文件格式。使用 Preon 的好处是它也会生成人类可读的文档。

      【讨论】:

        【解决方案3】:

        使用uniVocity-parsers,您不仅可以读取固定宽度的输入,还可以读取主从行(其中一行有子行)。

        这是一个例子:

        //1st, use a RowProcessor for the "detail" rows.
        ObjectRowListProcessor detailProcessor = new ObjectRowListProcessor();
        
        //2nd, create MasterDetailProcessor to identify whether or not a row is the master row.
        // the row placement argument indicates whether the master detail row occurs before or after a sequence of "detail" rows.
        MasterDetailListProcessor masterRowProcessor = new MasterDetailListProcessor(RowPlacement.TOP, detailProcessor) {
            @Override
            protected boolean isMasterRecord(String[] row, ParsingContext context) {
                //Returns true if the parsed row is the master row.
                return row[0].startsWith("B");
            }
        };
        
        FixedWidthParserSettings parserSettings = new FixedWidthParserSettings(new FixedWidthFieldLengths(4, 5, 40, 40, 8));
        
        // Set the RowProcessor to the masterRowProcessor.
        parserSettings.setRowProcessor(masterRowProcessor);
        
        FixedWidthParser parser = new FixedWidthParser(parserSettings);
        parser.parse(new FileReader(yourFile));
        
        // Here we get the MasterDetailRecord elements.
        List<MasterDetailRecord> rows = masterRowProcessor.getRecords();
        for(MasterDetailRecord masterRecord = rows){
         // The master record has one master row and multiple detail rows.
            Object[] masterRow = masterRecord.getMasterRow();
            List<Object[]> detailRows = masterRecord.getDetailRows();
        }
        

        披露:我是这个库的作者。它是开源免费的(Apache V2.0 许可)。

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-22
        • 2010-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 2017-04-15
        • 1970-01-01
        相关资源
        最近更新 更多