Java中CSV单元格正则匹配验证及MapReduce行为复现问题
解决CSV单元格正则校验的Java实现方案
看起来你已经走得挺远了——Map阶段的映射逻辑、FlightData对象都搞定了,剩下的单元格校验其实可以拆成「规则定义+校验逻辑+错误处理」三步来实现,下面给你具体的代码示例和思路:
第一步:先明确每个字段的正则校验规则
首先得根据你的FlightData字段,定义对应业务规则的正则表达式。比如假设你的CSV包含航班号、出发日期、延误分钟数、飞行里程这几个字段,规则可以这么写:
// 可根据你的实际业务需求调整这些正则 private static final String FLIGHT_NUM_REGEX = "^[A-Z]{2}\\d{3,4}$"; // 比如AA123或UA4567 private static final String DATE_REGEX = "^\\d{4}-\\d{2}-\\d{2}$"; // 标准YYYY-MM-DD格式 private static final String INTEGER_REGEX = "^\\d+$"; // 非负整数(延误分钟数不能是负数) private static final String DECIMAL_REGEX = "^\\d+\\.\\d{1,2}$"; // 最多两位小数的里程数
第二步:封装通用的校验工具方法
把校验逻辑抽成工具方法,避免重复代码,还能统一处理空值场景:
/** * 校验单个CSV字段是否符合正则规则 * @param fieldValue 单元格内容 * @param regex 校验规则 * @param allowEmpty 是否允许字段为空 * @return 校验结果 */ private boolean validateField(String fieldValue, String regex, boolean allowEmpty) { // 先处理空值情况 if (fieldValue == null || fieldValue.trim().isEmpty()) { return allowEmpty; } // 非空则匹配正则 return fieldValue.trim().matches(regex); }
第三步:在CSV行处理流程中加入校验
在你拆分CSV行、映射到FlightData的环节,插入校验逻辑,校验不通过的话可以选择跳过该行、记录错误日志或者抛出异常:
try (BufferedReader br = new BufferedReader(new FileReader("your_flights.csv"))) { String header = br.readLine(); // 跳过表头 String line; int lineNum = 1; while ((line = br.readLine()) != null) { lineNum++; String[] fields = line.split(","); // 先校验列数是否符合预期,避免数组越界 if (fields.length != 4) { System.err.printf("第%d行列数错误,跳过该行:%s%n", lineNum, line); continue; } // 逐个字段校验 boolean isFlightNumValid = validateField(fields[0], FLIGHT_NUM_REGEX, false); boolean isDateValid = validateField(fields[1], DATE_REGEX, false); boolean isDelayValid = validateField(fields[2], INTEGER_REGEX, true); // 允许延误分钟数为空 boolean isMileValid = validateField(fields[3], DECIMAL_REGEX, false); if (!isFlightNumValid || !isDateValid || !isDelayValid || !isMileValid) { System.err.printf("第%d行字段校验失败,跳过该行:%s%n", lineNum, line); continue; } // 校验通过,映射到FlightData并存入HashMap FlightData flight = new FlightData(); flight.setFlightNumber(fields[0].trim()); flight.setDepartureDate(LocalDate.parse(fields[1].trim())); flight.setDelayMinutes(fields[2].isEmpty() ? 0 : Integer.parseInt(fields[2].trim())); flight.setMiles(Double.parseDouble(fields[3].trim())); // 模拟MapReduce的Map阶段,这里用航班号作为key示例 yourHashMap.put(flight.getFlightNumber(), flight); } } catch (IOException e) { e.printStackTrace(); }
进阶优化建议
- 处理带引号的CSV字段:如果你的CSV存在带逗号的字段(比如
"New York, NY"),直接用split(",")会拆分错误,建议用OpenCSV这类成熟的CSV解析库,它能正确识别带引号的字段,还支持自定义校验器。 - 把校验整合到FlightData:可以把校验逻辑放到FlightData的构造方法或Setter里,创建对象时自动校验,比如:
public void setFlightNumber(String flightNumber) { if (!flightNumber.matches(FLIGHT_NUM_REGEX)) { throw new IllegalArgumentException("无效的航班号格式:" + flightNumber); } this.flightNumber = flightNumber; }
这样能保证存入HashMap的FlightData对象都是合法的。
内容的提问来源于stack exchange,提问作者Glennismade
相关产品推荐
相关产品推荐

