java 处理大文件

目的:

 前几天在开发过程中遇到一个需求: 读取一个大约5G的csv文件内容,将其转化为对象然后存储到redis中, 想着直接开大内存直接load 进入到内存中就行了,结果可想而知,5G的文件 ,Xmx 开到10G都没有解决,直接out of Memory  异常

1、读入大文件

  ①  直接load 进入到内存中


      这种处理大文件很容易造成 内存不够的问题

   String path = "F:\\originData\\snapshotDepth\\2022-06-20\\sh_stock_now.csv";
        File testFile = new File(path);
        List<String> file = FileUtil.readLines(testFile, Charset.defaultCharset());

     这种 500M的文件,堆内存一般会占用2.5G ,那么如果你去读一个5G的文件,那么内存直接起飞,所以这种不建议使用

 ②  按照行读取文件

  

     String path = "F:\\originData\\snapshotDepth\\2022-06-20\\sh_stock_now.csv";
        Scanner scanner = null;
        try (FileInputStream fileInputStream = new FileInputStream(path)) {
            scanner = new Scanner(fileInputStream);
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                log.info("对应的行的信息---{}", line);
            }
        } catch (Exception ex) {
            log.error("捕获到异常---{}", ex.getMessage(), ex);
        }

   这种因为是有按照一行行读取到内存当中,  所以耗时肯定增加 

③  使用common io 中的函数

 

   public void testCommon() {
        String path = "F:\\originData\\snapshotDepth\\2022-06-20\\sh_stock_now.csv";
        File file = new File(path);
        try {
            Integer count = 0;
            Long startTime = System.currentTimeMillis();
            final LineIterator lineIterator = FileUtils.lineIterator(file, "utf-8");
            while (lineIterator.hasNext()) {
                count++;
                String line = lineIterator.nextLine();
                if (count % 1000000 == 0) {
                    Long stepTime = System.currentTimeMillis();
                    log.info("读取100w 数据耗时为---{}", stepTime - startTime);
                    startTime = stepTime;
                }
            }
        } catch (Exception ex) {
            log.error("读取文件异常---{}", ex.getMessage(), ex);
        }
    }

 运行结果:

 

 每100w行的数据 大概耗时为1.5秒, 这个是在我的笔记本上运行的结果,如果在性能更好的机器上速度应该更快。

2、写入文件

   log.info("开始对FileWriter 写入文件进行计时");
        Long startTime = System.currentTimeMillis();
        String path = "F:\\originData\\test.txt";
        String content = "12312313";
        for (int i = 0; i < 100000; i++) {
            try (FileWriter fileWriter = new FileWriter(path, true)) {
                fileWriter.append(content);
            } catch (Exception ex) {
                log.error("捕获到异常---{}", ex.getMessage(), ex);
            }
        }
        Long stepEnd = System.currentTimeMillis();
        log.info("FileWriter 耗时为----{}", stepEnd - startTime);
        String path2 = "F:\\originData\\test2.txt";
        log.info("开始对 BufferedWriter 写入文件进行计时");
        for (int i = 0; i < 100000; i++) {
            try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path2, true))) {
                bufferedWriter.append(content);
            } catch (Exception ex) {
                log.error("捕获到异常---{}", ex.getMessage(), ex);
            }
        }
        Long stepNextEnd = System.currentTimeMillis();
        log.info("BufferedWriter 耗时为----{}", stepNextEnd - stepEnd);

        log.info("开始对 BufferedOutputStream  写入文件进行计时");
        String path3 = "F:\\originData\\test3.txt";
        for (int i = 0; i < 100000; i++) {
            try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(path3, true))) {
                bufferedOutputStream.write(content.getBytes());
            } catch (Exception ex) {
                log.error("捕获到异常---{}", ex.getMessage(), ex);
            }
        }
        Long stepNextStream = System.currentTimeMillis();
        log.info("BufferedWriter 耗时为----{}", stepNextStream - stepNextEnd);

        String path4 = "F:\\originData\\test4.txt";
        File file = new File(path4);
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            for (int i = 0; i < 100000; i++) {
                FileUtils.write(file, content, true);
            }
            log.info("FileUtils 耗时为----{}", System.currentTimeMillis() - stepNextStream);
        } catch (Exception ex) {
            log.error("捕获到异常---{}", ex.getMessage(), ex);
        }

运行结果

如果是写入字符串的话 还是建议使用BuffereOutputStream 

  • 1
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值