Java读取600万行的txt文件,内存溢出解决方案

可能造成内存溢出的原因:

  1. 一次性把txt文件读取到内存
  2. 频繁的new对象

实体类


import lombok.Data;
import java.io.Serializable;

/**
 * @author cpf
 * @date 2024/4/13 14:40
 */
@Data
public class User implements Serializable{

    private String user;

    private String positioningTime;

    private String latitude;

    private String longitude;

    private String locationId;

    public void clear() {
        setUser(null);
        setPositioningTime(null);
        setLatitude(null);
        setLongitude(null);
        setLocationId(null);
    }
}

可以使用对象池解决频繁new对象的问题
解决一次性把文件读取到内存: 可以使用文件流方式,使用java.util.Scanner类扫描文件的内容,一行一行连续地读取



import org.example.entity.User;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;

/**
 * @author cpf
 * @date 2024/4/13 15:45
 */
public class TestMe {

    private static final int USER_POOL_SIZE = 100; // 根据实际情况调整对象池大小

    private static Queue<User> userPool = new LinkedList<>();

    static {
        // 预先创建对象池中的User实例
        for (int i = 0; i < USER_POOL_SIZE; i++) {
            userPool.offer(new User());
        }
    }

    public static void main(String[] args) {
     
        String filePath = "src/main/resources/Gowalla_totalCheckins.txt";
        List<User> users = readData(filePath);
        for (int i = 0; i < 20; i++) {
            // 获取一个1-6000000的随机数
            int random = (int) (Math.random() * 6000000);
            System.out.println("第"+ random +"个数据: " + users.get(random));
        }
        System.out.println(users.size());


    }

    private static List<User> readData(String filePath) {
        List<User> userList = new ArrayList<>();
        FileInputStream fis  = null;
        Scanner sc = null;
        try {
            fis = new FileInputStream(filePath);
            sc = new Scanner(fis, "UTF-8");
            while (sc.hasNextLine()) {
                String line = sc.nextLine();
                User user = parseLine(line);
                if (user != null) {
                    userList.add(user);
                }
                // 在主程序中,使用完User对象后应将其归还到对象池
                userPool.offer(user);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                fis.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            if (sc != null) {
                sc.close();
            }
        }


        return userList;
    }


    private static User parseLine(String line) {
        String[] data = line.split("\t");
        if (data.length < 5) {
            System.err.println("数据格式错误:需要至少包含5个字段。");
            return null;
        }
        // 从对象池中获取一个User实例
        User user = userPool.poll();
        if (user == null) {
            // 对象池为空时,创建新的User实例
            user = new User();
        }
        // 清除原有数据并填充新行数据
        user.clear();
        user.setUser(data[0]);
        user.setPositioningTime(data[1]);
        user.setLatitude(data[2]);
        user.setLongitude(data[3]);
        user.setLocationId(data[4]);

        return user;
    }


}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java读取Excel文件时,有可能会遇到内存溢出的问题。导致内存溢出的原因主要有以下几个方面: 1. Excel文件过大:如果Excel文件非常大,包含大量的数据和工作表,读取整个文件可能会消耗大量的内存。尤其是使用HSSF或XSSF类库来处理大型Excel文件时,会将整个Excel文件加载到内存中,容易导致内存溢出。 2. 数据处理不当:在读取Excel文件时,如果没有合理的处理数据,比如对读取的每一行进行逐行处理,将数据存储到合适的数据结构中,可能会导致大量数据同时存在内存中,从而引发内存溢出。 3. 不适当地使用对象:在读取Excel时,可能需要使用大量的对象来存储表格、工作表、单元格等信息。如果使用不当,比如没有及时释放对象,或者创建了过多的对象,都会增加内存的占用,并有可能导致内存溢出。 为解决内存溢出的问题,可以采取以下措施: 1. 分块读取:可以将Excel文件按照一定的规则进行分块读取,每次只读取一部分数据,处理完后释放内存。这样可以降低内存占用,减少内存溢出的风险。 2. 使用流式处理:可以使用Apache POI提供的SXSSFWorkbook类库,通过流式处理方式来读取大型Excel文件。它将Excel文件划分为多个窗格,并在内存中保持一定数量的数据,可以有效地降低内存占用。 3. 及时释放资源:在读取Excel文件时,要注意及时释放不再使用的对象和资源,比如关闭工作表、关闭输入流等。这样可以避免内存泄漏和过度占用内存的情况。 综上所述,Java读取Excel文件内存溢出问题可以通过合理分块读取、流式处理和及时释放资源等方式来解决。需要根据具体的情况选择合适的处理方法,以确保程序在读取Excel文件时不会发生内存溢出

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微微一笑满城空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值