应定义带行号字段的自定义异常类,在逐行读取时维护从1开始的行计数器,解析失败时抛出含当前行号的异常,并在统一异常处理器中提取行号返回给调用方。

在 Java 文件导入(如 CSV、Excel 或文本文件)过程中,若解析出错需返回具体行号,关键是在抛出自定义异常时将当前行号作为参数传入,并在异常类中保存和暴露该信息。
定义带行号的自定义异常
创建一个继承 RuntimeException(或 Exception,按需选择是否强制捕获)的异常类,添加 lineNumber 字段,并提供构造方法和 getter:
public class ImportException extends RuntimeException {
private final int lineNumber;
public ImportException(String message, int lineNumber) {
super(message + " (行号: " + lineNumber + ")");
this.lineNumber = lineNumber;
}
public ImportException(String message, int lineNumber, Throwable cause) {
super(message + " (行号: " + lineNumber + ")", cause);
this.lineNumber = lineNumber;
}
public int getLineNumber() {
return lineNumber;
}
}
在文件读取循环中捕获并传递行号
以逐行读取 CSV 为例:使用 BufferedReader 或 OpenCSV 时,维护一个从 1 开始的行计数器,在解析失败时立即抛出带当前行号的异常:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 每读取一行,行号 +1(注意:首行为 1,不是 0)
- 解析字段、类型转换、业务校验等逻辑放在 try 块内
- 一旦出错(如空值、格式错误、违反约束),new ImportException("xxx", currentLine)
int lineNumber = 0;
try (BufferedReader reader = Files.newBufferedReader(path)) {
String line;
while ((line = reader.readLine()) != null) {
lineNumber++;
try {
// 解析该行,例如 split(",") + Integer.parseInt(...)
processLine(line);
} catch (NumberFormatException e) {
throw new ImportException("数值格式错误", lineNumber, e);
} catch (IllegalArgumentException e) {
throw new ImportException("数据不合法", lineNumber, e);
}
}
}
统一处理异常并返回给调用方
在服务层或 Controller 中捕获该异常,可直接获取行号用于日志记录或前端提示:
- 记录详细错误:log.error("导入失败,第{}行:{}", ex.getLineNumber(), ex.getMessage())
- 封装响应:返回 JSON 如
{"success":false,"message":"数值格式错误 (行号: 42)"} - 若使用 Spring,可通过 @ExceptionHandler 统一拦截 ImportException 并生成结构化错误响应
注意事项
确保行号准确:
- 跳过空行或注释行时,是否计入行号?建议「物理行号」——即文件中实际的行序号(readLine() 每调用一次算一行)
- 使用 Apache POI 读 Excel 时,行号从 0 开始(POI 的 Row.getRowNum()),需 +1 转为用户习惯的“第1行”
- 避免在 finally 或多线程中修改行号变量,防止错乱
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










