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

Java使用POJO读取CSV后提取指定数据的问题求助

问题排查与解决方案

我帮你梳理代码里的几个关键问题,这些要么是导致编译失败的致命错误,要么就是统计结果为0的直接原因:

1. createFlights方法的编译错误

你在createFlights里调用Flights构造函数时,传入了一堆未定义的变量(比如dep_time、sched_dep_time这类)——这些变量根本没从metadata数组里解析出来,代码连编译都通不过,更别说运行统计了。如果这些字段是CSV里实际存在的,你得从metadata里读取并转换类型;如果暂时不需要这些字段,建议简化Flights的构造函数,只保留你需要的字段,或者给这些参数赋默认值(比如0、null)。

2. CSV列索引越界问题

你说CSV有19列表头,但代码里用了metadata[19]来获取time_hour——Java数组是从0开始索引的,19对应的是第20列,这会直接抛出ArrayIndexOutOfBoundsException,中断文件读取流程,导致fdata为空,统计结果自然是0。另外也要再核对origin的列索引是否正确(比如如果Origin是第14列,索引13是对的,但一定要和实际CSV表头顺序对应)。

3. 空值处理逻辑的缺陷

你用list.contains("NA")跳过空值行,但这个逻辑有两个大坑:

  • 手动用split(",")拆分CSV会破坏带引号的字段(比如字段内容包含逗号时),直接导致列索引完全混乱;
  • contains("NA")会误判那些内容包含"NA"的有效字段(比如"NAXX"),错误跳过正常数据行。

建议要么逐个检查字段是否等于"NA",要么直接用成熟的CSV解析库(比如OpenCSV)来处理,避免手动拆分的各种边缘问题。

4. 字符串比较的潜在陷阱

如果CSV里的origin字段前后有空格(比如" EWR "),直接用equals("EWR")会返回false,导致统计不到目标数据。可以先调用trim()去除前后空格再做比较。

修正后的代码示例

我简化了代码,只保留核心逻辑,修复了上述问题:

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class NycFlights13 {
    public static void main(String[] args) {
        NYC13data dataLoader = new NYC13data();
        // 先打印总条目数,确认数据是否读取成功
        System.out.println("总读取条目数:" + dataLoader.flightData.fdata.size());
        
        int ewrCount = 0;
        for (Flight flight : dataLoader.flightData.fdata) {
            // 处理可能的null和空格问题
            if (flight.getOrigin() != null && flight.getOrigin().trim().equals("EWR")) {
                ewrCount++;
            }
        }
        System.out.println("EWR出发的条目数:" + ewrCount);
    }
}

class NYC13data {
    FlightData flightData = new FlightData();

    public NYC13data() {
        flightData.readFileFromCSV("C:\\Users\\boonl\\Desktop\\R Assignment\\flights.csv");
    }
}

class FlightData {
    public List<Flight> fdata;

    public FlightData() {
        fdata = new ArrayList<>();
    }

    public List<Flight> readFileFromCSV(String fileName) {
        Path pathToFile = Paths.get(fileName);
        try (BufferedReader br = Files.newBufferedReader(pathToFile, StandardCharsets.US_ASCII)) {
            // 跳过表头行
            br.readLine();
            String line;
            while ((line = br.readLine()) != null) {
                String[] variables = line.split(",");
                // 先检查列数是否符合预期
                if (variables.length != 19) {
                    System.out.println("跳过格式错误的行:" + line);
                    continue;
                }
                
                // 逐个检查字段是否为NA
                boolean hasInvalidValue = false;
                for (String var : variables) {
                    if ("NA".equals(var.trim())) {
                        hasInvalidValue = true;
                        break;
                    }
                }
                if (hasInvalidValue) {
                    continue;
                }

                try {
                    Flight flight = createFlight(variables);
                    fdata.add(flight);
                } catch (NumberFormatException e) {
                    System.out.println("跳过数据类型错误的行:" + line);
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return fdata;
    }

    private static Flight createFlight(String[] metadata) {
        // 假设Origin是第14列(索引13),请根据实际CSV表头调整
        String origin = metadata[13].trim();
        // 只保留需要的字段,其他字段可按需添加
        return new Flight(origin);
    }
}

class Flight {
    private String origin;

    // 简化构造函数,只保留核心字段
    public Flight(String origin) {
        this.origin = origin;
    }

    // 符合Java规范的驼峰命名getter
    public String getOrigin() {
        return origin;
    }

    public void setOrigin(String origin) {
        this.origin = origin;
    }

    @Override
    public String toString() {
        return "Flight [origin=" + origin + "]";
    }
}

额外建议

  • 强烈建议使用专业CSV解析库(比如OpenCSV),它能自动处理带引号的字段、换行、空值等各种复杂情况,比手动split可靠得多;
  • 代码命名尽量符合Java规范(类名首字母大写、驼峰命名法),能大幅提升代码可读性;
  • 可以添加更多调试输出(比如打印每条读取到的origin值),方便排查数据是否被正确解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 12:32:47