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

超30万行CSV文件匹配输出异常问题技术求助

大CSV文件匹配后输出异常的问题分析与解决

问题场景

读取两个CSV文件存入ArrayList后进行内容匹配,小文件(行数≤20)处理正常,但当其中一个CSV超过30万行时,匹配结果输出异常:1.5万行的РФМ.csv内容可完整显示,30万+行的БД.csv仅输出299000行后的内容,但单独输出listBD索引0-299000的元素均正常。两个文件包含姓名与出生日期数据,未排序。

原代码如下:

public class Podft {    
    public static void main(String[] args) throws IOException{        
        ArrayList<String> listBD = new ArrayList<>();        
        ArrayList<String> listPFM = new ArrayList<>();        
        ArrayList<String> result = new ArrayList<>();        
        BufferedReader readerBD = new BufferedReader(new FileReader("C:\Users\d\Doc\БД.csv"));        
        BufferedReader readerPFM = new BufferedReader(new FileReader("C:\Users\d\Doc\РФМ.csv"));        
        String lineBD = readerBD.readLine();        
        String linePFM = readerPFM.readLine();        
        while (lineBD != null) {            
            listBD.add(lineBD);            
            lineBD = readerBD.readLine();            
        }        
        while (linePFM != null) {            
            listPFM.add(linePFM);            
            linePFM = readerPFM.readLine();        
        }
        for(int i = 0; i < listBD.size(); i++){            
            for(int j = 0; j < listPFM.size(); j++){                
                if(listBD.get(i).equals(listPFM.get(j))){                    
                    result.add(listPFM.get(j));                
                }            
            }        
        }        
        for (String q : result){            
            System.out.println(q);
        }    
    }
}

问题原因

  1. 控制台输出缓冲区限制:绝大多数终端(Windows命令提示符、IDEA默认控制台等)都有输出行数/缓冲区大小限制,当输出内容过多时,早期的输出会被覆盖或丢弃,只能看到最后一部分内容。这是最核心的原因——并非程序未生成前面的结果,而是控制台无法显示全部内容。
  2. 双重循环的性能灾难:30万行×1.5万行=4.5亿次循环,会导致程序运行极慢,甚至因内存波动间接影响输出稳定性。
  3. 资源未正确回收:代码未手动关闭BufferedReader,大文件场景下可能引发资源泄漏,导致未知异常。

解决方案

1. 替换控制台输出:将结果写入文件

直接输出到控制台受限于缓冲区,改为写入文件即可查看完整结果:

// 替换原输出循环
try (BufferedWriter writer = new BufferedWriter(new FileWriter("C:\\Users\\d\\Doc\\匹配结果.csv"))) {
    for (String q : result) {
        writer.write(q);
        writer.newLine();
    }
} catch (IOException e) {
    e.printStackTrace();
}

2. 优化匹配性能:用HashSet替代ArrayList查找

将较小的集合(РФМ.csv)存入HashSet,把匹配时间复杂度从O(m*n)降至O(m),性能提升几个数量级:

// 将listPFM转为HashSet
HashSet<String> pfmSet = new HashSet<>(listPFM);

// 匹配逻辑简化为单循环
for (String bdLine : listBD) {
    if (pfmSet.contains(bdLine)) {
        result.add(bdLine);
    }
}

3. 改进资源管理:使用try-with-resources自动关闭流

避免手动管理流的关闭,防止资源泄漏:

// 读取БД.csv
try (BufferedReader readerBD = new BufferedReader(new FileReader("C:\\Users\\d\\Doc\\БД.csv"))) {
    String lineBD;
    while ((lineBD = readerBD.readLine()) != null) {
        listBD.add(lineBD);
    }
}

// 读取РФМ.csv
try (BufferedReader readerPFM = new BufferedReader(new FileReader("C:\\Users\\d\\Doc\\РФМ.csv"))) {
    String linePFM;
    while ((linePFM = readerPFM.readLine()) != null) {
        listPFM.add(linePFM);
    }
}

4. 可选:用专业CSV库处理复杂场景

如果CSV存在多行字段、分隔符转义等情况,手动读取行可能出错,推荐使用OpenCSV等库按字段处理:

// 示例:用OpenCSV读取并拼接匹配键
try (CSVReader readerBD = new CSVReader(new FileReader("C:\\Users\\d\\Doc\\БД.csv"))) {
    String[] nextLine;
    while ((nextLine = readerBD.readNext()) != null) {
        // 按姓名+出生日期拼接匹配键
        String key = nextLine[0] + "," + nextLine[1];
        listBD.add(key);
    }
}

整合后的完整代码

import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;

public class Podft {
    public static void main(String[] args) throws IOException {
        ArrayList<String> listBD = new ArrayList<>();
        ArrayList<String> listPFM = new ArrayList<>();
        ArrayList<String> result = new ArrayList<>();

        // 读取БД.csv,自动关闭流
        try (BufferedReader readerBD = new BufferedReader(new FileReader("C:\\Users\\d\\Doc\\БД.csv"))) {
            String lineBD;
            while ((lineBD = readerBD.readLine()) != null) {
                listBD.add(lineBD);
            }
        }

        // 读取РФМ.csv,自动关闭流
        try (BufferedReader readerPFM = new BufferedReader(new FileReader("C:\\Users\\d\\Doc\\РФМ.csv"))) {
            String linePFM;
            while ((linePFM = readerPFM.readLine()) != null) {
                listPFM.add(linePFM);
            }
        }

        // 用HashSet优化匹配性能
        HashSet<String> pfmSet = new HashSet<>(listPFM);
        for (String bdLine : listBD) {
            if (pfmSet.contains(bdLine)) {
                result.add(bdLine);
            }
        }

        // 将结果写入文件,避免控制台输出限制
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("C:\\Users\\d\\Doc\\匹配结果.csv"))) {
            for (String q : result) {
                writer.write(q);
                writer.newLine();
            }
        }

        // 输出匹配结果数量到控制台
        System.out.println("匹配完成,共找到 " + result.size() + " 条匹配记录");
    }
}

内容的提问来源于stack exchange,提问作者Дмитрий Сергеевич

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:32:06