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

处理大CSV文件时Scanner抛出NoSuchElementException异常求助

问题分析与解决方案

错误根源

java.util.NoSuchElementException: No line found 本质是某一行的CSV字段数量不足8个,导致rowScanner.next()尝试读取不存在的元素。常见触发场景:

  • 第75000行附近存在空行、字段缺失的不完整行
  • 字段包含逗号(比如城市名是"Paris, France"),直接用逗号做分隔符会把单个字段拆成多个,后续读取时字段数就不够了
  • 文件末尾存在空行,lineScanner.hasNext()判断为有内容,但实际读取的是空字符串,rowScanner自然拿不到元素

修复步骤

  1. 快速定位问题行
    在循环中加入行号计数和内容打印,精准定位出错的行:

    int lineNum = 1;
    lineScanner.nextLine(); // 跳过表头,行号从2开始
    lineNum++;
    while (lineScanner.hasNext()) {
        String line = lineScanner.nextLine();
        lineNum++;
        System.out.println("当前处理行号:" + lineNum + ",内容:" + line); // 新增调试代码
        Scanner rowScanner = new Scanner(line);
        // 后续原有代码不变
    }
    

    运行后就能看到报错前最后处理的行,直接去CSV文件中检查该行的格式问题。

  2. 替换CSV解析方式
    Scanner完全不支持带引号的逗号字段,改用专业CSV解析库(比如OpenCSV)处理更可靠:

    // Maven依赖示例(需先引入)
    // <dependency>
    //     <groupId>com.opencsv</groupId>
    //     <artifactId>opencsv</artifactId>
    //     <version>5.6</version>
    // </dependency>
    
    private static void FillPopulation(){
        Connection con = null;
        try{
            con = DriverManager.getConnection(DATA_BASE);
            CSVReader reader = new CSVReader(new FileReader(EXCEL_TO_PROCESS));
            String[] nextLine;
            reader.readNext(); // 跳过表头
            
            while ((nextLine = reader.readNext()) != null) {
                // 自动处理带引号的逗号,直接拿到每行的字段数组
                if (nextLine.length != 8) {
                    System.out.println("格式错误行:" + Arrays.toString(nextLine));
                    continue; // 跳过错误行,避免程序中断
                }
                String year = nextLine[0];
                String avgTemp = nextLine[1];
                String minTemp = nextLine[2];
                String maxTemp = nextLine[3];
                String cityName = nextLine[4];
                String countryName = nextLine[5];
                String latitude = nextLine[6];
                String longitude = nextLine[7];
                
                // 简化空值处理
                avgTemp = avgTemp.isEmpty() ? "0" : avgTemp;
                minTemp = minTemp.isEmpty() ? "0" : minTemp;
                maxTemp = maxTemp.isEmpty() ? "0" : maxTemp;
                
                // 使用PreparedStatement避免SQL注入,同时提升执行效率
                String query = "INSERT INTO CityTemps VALUES(?, ?, ?, ?, ?, ?, ?, ?)";
                PreparedStatement pstmt = con.prepareStatement(query);
                pstmt.setString(1, countryName);
                pstmt.setString(2, cityName);
                pstmt.setString(3, year);
                pstmt.setString(4, avgTemp);
                pstmt.setString(5, maxTemp);
                pstmt.setString(6, minTemp);
                pstmt.setString(7, latitude);
                pstmt.setString(8, longitude);
                pstmt.executeUpdate();
            }
        }catch(Exception e){
            e.printStackTrace();
        } finally {
            // 强制关闭资源,避免泄漏
            try {
                if (con != null) con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
  3. 额外优化建议

    • 不要在循环内重复创建Statement,复用PreparedStatement能大幅提升数据库操作效率
    • 必须在finally块中关闭数据库连接和文件流,防止资源泄漏
    • 空值处理可以用三元运算符简化代码逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:58:11