Java读取主机文件行的每条记录并存储在列表中

问题描述 投票:0回答:1

我正在尝试读取大型机文件以用java写入XML。我希望得到如下 XML 示例所示的输出数据。目前,我得到的 FUND、FUNDID 等为空值。我正在尝试存储前一行的值并在下一行中打印这些值,直到满足新的基金标准。寻求帮助,例如如果资金在新行中匹配=记录已开始,请阅读下一行以获取匹配条件,然后打印记录列表。然后如果再次基金匹配开始新记录。

AMFDS 2045 TDRF R 1XA 100.0%     5,634.40        376.91         251.07            .00            .00       6,260.93-M          .00
                                                                                                           1.45-M

我需要将输出打印为

<ACTIVITY>
<FUND><![CDATA[AMFDS 2045 TDRF R]]></FUND>
<FUND_ID><![CDATA[1X]]></FUND_ID>
<SOURCE><![CDATA[A]]></SOURCE>
<MIXPERCENTAGE><![CDATA[100.0%]]></MIXPERCENTAGE>
<YTD><![CDATA[376.91]]></YTD>
<BALANCE><![CDATA[6,260.93]]></BALANCE>
</ACTIVITY>
<ACTIVITY>
<FUND><![CDATA[AMFDS 2045 TDRF R]]></FUND>
<FUND_ID><![CDATA[1X]]></FUND_ID>
<SOURCE><![CDATA[A]]></SOURCE>
<MIXPERCENTAGE><![CDATA[100.0%]]></MIXPERCENTAGE>
<YTD><![CDATA[376.91]]></YTD>
<BALANCE><![CDATA[1.45]]></BALANCE>
</ACTIVITY>

 

private void processFundRecords(Supplier<Stream<String>> streamSupplier, Map<String, List<String>> recordMap){
        List<String> fundLines = new ArrayList<>();
        streamSupplier.get().forEach(line -> {
                    if (isFund(streamSupplier))
            {
                // If it's the start of a new fund, process the previous fund lines
                if (!fundLines.isEmpty()) {
                    processFundData((Supplier<Stream<String>>) fundLines, recordMap);
                    fundLines.clear(); // Reset the fund lines
                }
                fundLines.add(line); // Start a new fund record
            } else if (isPartOfSameFundRecord(streamSupplier) || line.startsWith("LOAN")) {
                fundLines.add(line); // Add to the current fund record
            }
        });
                    // Process any remaining fund lines
        if (!fundLines.isEmpty()) {
            processFundData((Supplier<Stream<String>>) fundLines, recordMap);
        }
    }

    private boolean ignoreLines(Supplier<Stream<String>> streamSupplier) {
        return streamSupplier.get().anyMatch(line ->
                line.startsWith("** TOTAL") ||
                        line.startsWith("***** INVESTMENTS") ||
                        line.startsWith("***** SOURCES")
        );
    }

    private void processFundData(Supplier<Stream<String>> streamSupplier, Map<String, List<String>> recordMap) {
        if (streamSupplier.get().allMatch(s -> s.length() == 0)) {
            return;
        }
        if(!ignoreLines(streamSupplier)) {
            recordMap.put(FUND, streamSupplier.get()
                    .map(s -> s.substring(0, 17).trim())
                    .collect(Collectors.toList()));
            recordMap.put(FUNDID, streamSupplier.get()
                    .map(s -> s.substring(18, 20).trim())
                    .collect(Collectors.toList()));
            recordMap.put(SOURCE, streamSupplier.get()
                    .map(s -> s.substring(20, 21).trim())
                    .collect(Collectors.toList()));
            recordMap.put(MIXPERCENTAGE,
                    streamSupplier.get().map(s -> s.substring(22, 28).trim())
                            .collect(Collectors.toList()));
            recordMap.put(YTD, streamSupplier.get().map(s -> s.substring(43, 55).trim())
                    .collect(Collectors.toList()));
            recordMap.put(MBALANCE, streamSupplier.get()
                    .filter(s -> s.length() > 115 && s.substring(115, 117).contains("-M"))
                    .map(s -> s.substring(103, 115).trim())
                    .collect(Collectors.toList()));
        }
}

 

if (isPartOfSameFundRecord(streamSupplier)) {
                    fundFound = true;
                    activityKeyBucketMap = initializeNewMap(activityKeyBucketList);
                    processFundData(streamSupplier, activityKeyBucketMap);

                    //System.out.println("#### FUND ###");
                }
java java-17
1个回答
0
投票

试试我的运气:

  1. 创建一个方法来简化每行数据的处理并使其更具可读性
  2. 声明一个明确的方法来检测新基金何时开始。
  3. 一旦发现新基金,您应该积累额度,直到下一个基金开始。
  4. 将格式化数据写入 XML 结构。

这里有一个可能对您有用的改进:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class FundProcessor {

    private static final String FUND = "FUND";
    private static final String FUND_ID = "FUND_ID";
    private static final String SOURCE = "SOURCE";
    private static final String MIX_PERCENTAGE = "MIXPERCENTAGE";
    private static final String YTD = "YTD";
    private static final String BALANCE = "BALANCE";

    public static void main(String[] args) {
        // Assuming this is where you read lines from a file or another source
        Supplier<Stream<String>> streamSupplier = () -> Stream.of(
                "AMFDS 2045 TDRF R 1XA 100.0%     5,634.40        376.91         251.07"
                // Add more lines as needed for testing
        );

        List<String> records = processRecords(streamSupplier);
        records.forEach(System.out::println);
    }

    private static List<String> processRecords(Supplier<Stream<String>> streamSupplier) {
        List<String> fundLines = new ArrayList<>();
        List<String> outputXml = new ArrayList<>();

        streamSupplier.get().forEach(line -> {
            if (isNewFund(line)) {
                if (!fundLines.isEmpty()) {
                    outputXml.add(processFundData(fundLines));
                    fundLines.clear();
                }
            }
            fundLines.add(line);
        });

        if (!fundLines.isEmpty()) {
            outputXml.add(processFundData(fundLines));
        }

        return outputXml;
    }

    private static boolean isNewFund(String line) {
        // Implement your logic to determine if the line starts a new fund
        return line.matches(".*\\d+XA.*");  // Example regex, adjust according to actual criteria
    }

    private static String processFundData(List<String> fundLines) {
        // Extract data from the first line or further lines as needed
        String firstLine = fundLines.get(0);
        String fund = firstLine.substring(0, 17).trim();
        String fundId = firstLine.substring(18, 20).trim();
        String source = firstLine.substring(20, 21).trim();
        String mixPercentage = firstLine.substring(21, 28).trim();
        String ytd = firstLine.substring(43, 50).trim();
        String balance = firstLine.substring(57, 65).trim().replace(",", "");

        return String.format("<ACTIVITY>\n<FUND><![CDATA[%s]]></FUND>\n<FUND_ID><![CDATA[%s]]></FUND_ID>\n<SOURCE><![CDATA[%s]]></SOURCE>\n<MIXPERCENTAGE><![CDATA[%s]]></MIXPERCENTAGE>\n<YTD><![CDATA[%s]]></YTD>\n<BALANCE><![CDATA[%s]]></BALANCE>\n</ACTIVITY>", fund, fundId, source, mixPercentage, ytd, balance);
    }
}

您可以编辑适合您的方式。我希望它有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.