You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch 如何读取文件特定区块的字段定义与实际数据?

Spring Batch 分区块文件读取实现方案

核心思路是通过自定义带状态控制的FlatFileItemReader,分两个阶段完成文件读取,全程不需要拆分多Step,逻辑更简洁。

具体实现步骤

  • 第一步:给Reader增加状态标识,控制读取区间
    定义三个读取状态:读取字段区、读取数据区、读取结束,初始状态为读取字段区:
    1. 逐行读取文件,读到START_OF_FIELDS标记后开始收集后续行内容作为目标字段,直到读到END_OF_FIELDS停止,把收集到的字段列表缓存在Reader内部,状态切换为读取数据区
    2. 继续逐行读取,读到START_OF_DATA标记后,先解析第一行表头,拿到你缓存的目标字段对应的列下标,后续行按分隔符切分后只提取对应下标的值组装成数据对象,直到读到END_OF_DATA,状态切换为读取结束,返回null终止读取
  • 第二步:核心代码示例
// 自定义分段Reader
public class SectionedFileReader extends FlatFileItemReader<Object> {
    // 读取状态枚举
    private enum ReadState { READ_FIELD_SECTION, READ_DATA_SECTION, COMPLETE }
    private ReadState currentState = ReadState.READ_FIELD_SECTION;
    // 缓存的目标字段列表
    private List<String> targetFields = new ArrayList<>();
    // 表头与下标的映射关系
    private Map<String, Integer> fieldIndexMap = new HashMap<>();
    private final DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer("|");

    @Override
    protected Object doRead() throws Exception {
        while (currentState != ReadState.COMPLETE) {
            String line = readLine();
            if (line == null) break;
            // 处理字段配置区
            if (currentState == ReadState.READ_FIELD_SECTION) {
                if (line.equals("START_OF_FIELDS")) continue;
                if (line.equals("END_OF_FIELDS")) {
                    currentState = ReadState.READ_DATA_SECTION;
                    continue;
                }
                targetFields.add(line.trim());
                continue;
            }
            // 处理数据区
            if (currentState == ReadState.READ_DATA_SECTION) {
                if (line.equals("START_OF_DATA")) continue;
                if (line.equals("END_OF_DATA")) {
                    currentState = ReadState.COMPLETE;
                    continue;
                }
                // 首次进入数据区先处理表头,建立映射关系
                if (fieldIndexMap.isEmpty()) {
                    String[] headers = tokenizer.tokenize(line).getValues();
                    for (int i = 0; i < headers.length; i++) {
                        fieldIndexMap.put(headers[i], i);
                    }
                    continue;
                }
                // 只提取目标字段对应的值
                FieldSet lineContent = tokenizer.tokenize(line);
                Map<String, String> data = new HashMap<>();
                for (String field : targetFields) {
                    data.put(field, lineContent.readString(fieldIndexMap.get(field)));
                }
                // 此处可替换为你自定义的业务实体类返回
                return data;
            }
        }
        return null;
    }
}
  • 第三步:装配到Step即可使用
    直接把自定义Reader注入到普通的Step配置中,后续的Processor和Writer正常处理Reader返回的数据即可,不需要额外做跨Step上下文传递。

注意:你给出的示例文件中START_OF_FIELDS标记拼写错误为STARRT_OF_FIELDS,实际使用时请先确认文件标记的正确性,避免匹配失败。

内容的提问来源于stack exchange,提问作者TechieGirl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 01:06:03