最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何安全构建 CSV 读取器解析信用卡交易数据
时间:2026-06-30 09:20:53 编辑:袖梨 来源:一聚教程网
本文详解如何修复因 scanner 未初始化导致的 nullpointerexception,并实现一个健壮的 csv 解析器,用于统计信用卡交易总数、借记/贷记笔数及借记总金额。
本文详解如何修复因 scanner 未初始化导致的 nullpointerexception,并实现一个健壮的 csv 解析器,用于统计信用卡交易总数、借记/贷记笔数及借记总金额。
在开发 CSV 读取器分析信用卡数据时,NullPointerException 是初学者最常见的陷阱之一——其根源往往在于对象使用早于初始化。你的代码中,private Scanner s; 仅声明而未初始化,却在 scanner() 方法开头就调用 s.nextLine(),此时 s 为 null,必然触发异常。
✅ 正确的初始化时机与流程
应将 Scanner 初始化移至构造函数或 scanner() 方法起始处,确保在任何读取操作前完成实例化。同时,需明确区分“文件打开失败”与“文件已读完”两类异常:FileNotFoundException 表示文件不存在;NoSuchElementException 表示无更多行可读——二者不可混淆处理。
以下是重构后的核心逻辑(含完整功能扩展):
import java.io.File;import java.io.FileNotFoundException;import java.util.Scanner;public class CsvReader { private Scanner s; private int totalTransactions = 0; private int debitCount = 0; private int creditCount = 0; private double totalDebitAmount = 0.0; // 构造函数:立即初始化 Scanner(若文件存在) public CsvReader(String fileName) { try { s = new Scanner(new File(fileName)); } catch (FileNotFoundException e) { System.err.println("❌ 错误:文件 '" + fileName + "' 未找到。请检查路径和文件名。"); s = null; // 显式设为 null,避免后续误用 } } // 主解析方法 public void analyze() { if (s == null) return; // 文件加载失败,直接退出 while (s.hasNextLine()) { String line = s.nextLine().trim(); if (line.isEmpty()) continue; // 跳过空行 String[] fields = getTokens(line); if (fields.length < 5) { System.err.println("⚠️ 警告:跳过格式异常行(字段不足5个): " + line); continue; } // 假设第3列为交易类型("Debit" / "Credit"),第5列为金额(如 "$123.45") String type = fields[2].trim(); String amountStr = fields[4].trim().replace("$", "").replace(",", ""); try { double amount = Double.parseDouble(amountStr); totalTransactions++; if ("Debit".equalsIgnoreCase(type)) { debitCount++; totalDebitAmount += amount; } else if ("Credit".equalsIgnoreCase(type)) { creditCount++; } } catch (NumberFormatException e) { System.err.println("⚠️ 警告:金额解析失败,跳过该行: " + line); } } s.close(); // ✅ 关闭资源,防止内存泄漏 printSummary(); } // 你原有的 CSV 解析逻辑(已优化:避免空指针 & 提升鲁棒性) private String[] getTokens(String input) { String[] tokens = new String[5]; for (int i = 0; i < tokens.length; i++) tokens[i] = ""; int index = 0, pointer = 0; boolean inQuotes = false; while (pointer < input.length()) { char c = input.charAt(pointer); if (c == '"') { inQuotes = !inQuotes; } else if (c == ',' && !inQuotes) { index++; if (index >= tokens.length) break; // 防越界 } else { tokens[index] += c; } pointer++; } return tokens; } private void printSummary() { System.out.println("? 交易统计报告"); System.out.println("├─ 总交易数: " + totalTransactions); System.out.println("├─ 借记交易数: " + debitCount); System.out.println("├─ 贷记交易数: " + creditCount); System.out.printf("└─ 借记总金额: $%.2f%n", totalDebitAmount); } // 使用示例 public static void main(String[] args) { CsvReader reader = new CsvReader("visadata.txt"); reader.analyze(); }}
⚠️ 关键注意事项
- 永远先检查 s != null:在调用 hasNextLine() 或 nextLine() 前,确保 Scanner 已成功初始化;
- 及时关闭资源:s.close() 必须执行,否则可能引发文件句柄泄漏;
- 字段索引需与实际 CSV 结构对齐:示例假设第3列是类型、第5列是金额,请根据真实数据调整 fields[2] 和 fields[4];
- 金额字符串预处理:移除 $、, 等非数字字符后再 parseDouble,避免 NumberFormatException;
- 空行与异常行容错:添加 trim() 和长度校验,提升程序健壮性。
通过以上重构,你不仅能彻底规避 NullPointerException,还能获得一个可扩展、易维护、生产就绪的信用卡 CSV 分析工具。
相关文章
- Steam新一代手柄要来了 突发上架或暗示快要开卖 07-02
- 我的世界怎样把按键调大 07-02
- 三角洲行动s10猫鼠游戏任务通关攻略 07-02
- 我的世界皮肤文件夹名称是什么 07-02
- 三角洲行动S10:突入禁区任务攻略 07-02
- 我的世界地狱堡垒的坐标指令是哪个 07-02