Groovy过滤CSV文件时如何基于变量跳过指定行数后执行日期筛选
Groovy CSV日期过滤代码改造方案
现有代码无法实现跳过指定行的核心原因是:你把行计数、跳过判断的逻辑写在了filterLine方法调用外部,这段逻辑只会在程序启动时执行1次,根本不会随着逐行读取文件触发,自然达不到跳过前N行的效果。
基于现有代码完全可以实现需求,只需要把跳过逻辑嵌入逐行处理的闭包内即可,改造点如下:
- 将传入的跳过行数字符串参数转为整数,避免字符串类型比较导致的逻辑错误
- 把行计数器的判断逻辑移到
filterLine的逐行处理闭包中,前N行直接放行不做日期校验 - 用Groovy自带的
withPrintWriter自动管理输出流资源,避免未关闭流导致的文件写入不全问题 - 提前把日期列索引参数转为整数,不用每行处理时重复转换
改造后可直接运行的代码如下:
import java.time.format.DateTimeFormatter import java.time.LocalDate // 入参顺序:0=待处理CSV文件名 1=过滤阈值日期(dd.MM.yyyy格式) 2=日期所在列索引(从0开始计数) 3=原冗余路径参数 4=需跳过的前导行数 def skipLines = Integer.parseInt(this.args[4]) String file = this.args[0] String outputFile = file + "_filtered.csv" def pathInput = "../input/" + file def pathOutput = "../output/" + outputFile String thresholdDateStr = this.args[1] def dateColumnIndex = Integer.parseInt(this.args[2]) final DATE_FMT = DateTimeFormatter.ofPattern('dd.MM.yyyy') def targetDate = LocalDate.parse(thresholdDateStr, DATE_FMT) def inputCsv = new File(pathInput) def outputCsv = new File(pathOutput) def currentLineNum = 0 outputCsv.withPrintWriter { writer -> inputCsv.filterLine(writer) { line -> // 前N行直接保留,不做过滤 if (currentLineNum < skipLines) { currentLineNum++ return true } // 跳过指定行数后执行日期过滤 def columnParts = line.split(';') def lineDate = LocalDate.parse(columnParts[dateColumnIndex], DATE_FMT) currentLineNum++ return lineDate >= targetDate } } println pathInput println pathOutput
使用说明:
- 处理带1行表头的CSV时,第5个入参传
1即可自动保留表头、从第二行开始过滤 - 如果文件前有2行及以上的说明内容,只需要把对应入参改成要跳过的行数即可,无需调整代码
- 原代码中定义后未使用的
path变量已移除,不影响原有功能
内容的提问来源于stack exchange,提问作者Gusdl
相关产品推荐
相关产品推荐

