大批量到处excel,防止内存溢出

2024-05-13 13:32

本文主要是介绍大批量到处excel,防止内存溢出,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近在做项目功能时 ,发现有20万以上的数据。要求导出时直接导出成压缩包。原来的逻辑是使用poi导出到excel,他是操作对象集合然后将结果写到excel中。

使用poi等导出时,没有考虑数据量的问题,大数据量无法满足,有个几千行jvm就哭了。更别提几万行几百万行数据了。

经过一天的研究发现一种不会消耗过多内存的方法:

导出成csv格式

大数据量的导出成csv格式分为以下几步:

1.首先引入需要的jar包 一下是我maven的配置方式

1

2

3

4

5

6

7

8

9

10

<dependency>

        <groupId>org.mvel</groupId>

        <artifactId>mvel2</artifactId>

        <version>2.2.8.Final</version>

    </dependency>

    <dependency>

        <groupId>net.sourceforge.javacsv</groupId>

        <artifactId>javacsv</artifactId>

        <version>2.0</version>

    </dependency>

 2.以下是具体的执行代码,我是用的是jdbcTemplate

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

public class DownloadVehicleRepair extends AbstractJob {

 

    @Autowired

    private JdbcTemplate jdbcTemplate;

 

    @Override

    protected void executeBusiness(Long aLong) {

        System.out.println("开始执行!!!!!!!!!!");

        final String fileName = "车辆维修清单.csv";//压缩包里面的文件

        final String[] header = {"序号""第三方机构代码""机构名称""分公司""合作机构""单位类别""主品牌""品牌名称",

                "被投诉""涉及欺诈""黑名单""审核状态""维护时间""维护人员代码"};

        final String sql = "您需要执行sql”;

 

        jdbcTemplate.execute(new PreparedStatementCreator() {

            @Override

            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {

                PreparedStatement pstmt = connection.prepareStatement(sql);

                return pstmt;

            }

        }, new PreparedStatementCallback<Integer>() {

            @Override

            public Integer doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException {

                ResultSet rs = preparedStatement.executeQuery();

                try {

                    CsvUtil.writeCsv(RuntimeEnvironmentUtil.getValue(SysConstent.code,SysConstent.path) + "\\VehicleRepairDetail.zip",

                            fileName, header, rs);//RuntimeEnvironmentUtil.getValue()是为了获取你导出到服务器的路径

                catch (Exception e) {

                    e.printStackTrace();

                }

                return 0;

            }

        });

        System.out.println("导出完成!!!!!!!!!!!");

 

    }

}

 3.以下是帮助类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

public class CsvUtil {

    // 编码类型

    public static final Charset CHARSET = Charset.forName("GBK");

 

    // 分隔符

    public static final char DELIMITER = ',';

 

    // 文件后缀

    public static final String SUFFIX = ".csv";

 

 

    public static void writeCsv(OutputStream out, String[] header, ResultSet rs)

            throws IOException, SQLException {

        CsvWriter writer = null;

        try {

            writer = new CsvWriter(out, CsvUtil.DELIMITER, CsvUtil.CHARSET);

            writeCsv(writer, header, rs);

        finally {

            if (writer != null)

                writer.close();

        }

    }

 

    public static void writeCsv(CsvWriter writer, String[] header, ResultSet rs)

            throws IOException, SQLException {

        if (header != null)

            writer.writeRecord(header);

        ResultSetMetaData md = rs.getMetaData();

        int columnCount = md.getColumnCount();

        while (rs.next()) {

            for (int i = 1; i <= columnCount; i++)

                writer.write(rs.getString(i));

            writer.endRecord();

        }

    }

 

    public static void writeCsv(File file, String[] header, ResultSet rs)

            throws IOException, SQLException {

        BufferedOutputStream out = null;

        FileOutputStream fileOutputStream = null;

        try {

            fileOutputStream = new FileOutputStream(file);

            out = new BufferedOutputStream(fileOutputStream);

            writeCsv(out, header, rs);

        finally {

            if (out != null) {

                out.flush();

                out.close();

            }

            if (fileOutputStream != null) {

                fileOutputStream.close();

            }

        }

    }

 

    public static void writeCsv(String csvFilePath, String[] header,

                                ResultSet rs) throws IOException, SQLException {

        writeCsv(new File(csvFilePath), header, rs);

    }

 

    public static void writeCsv(String zipFilePath, String csvName, String[] header, ResultSet rs)

            throws IOException, SQLException {

        FileOutputStream fos = null;

        BufferedOutputStream bos = null;

        ZipOutputStream zos = null;

        try {

            fos = new FileOutputStream(zipFilePath);

            bos = new BufferedOutputStream(fos);

            zos = new ZipOutputStream(bos);

            zos.putNextEntry(new ZipEntry(csvName));

            writeCsv(zos, header, rs);

        finally {

            StreamUtil.flush(zos);

            StreamUtil.close(zos);

            //StreamUtil.flush(bos);

            StreamUtil.close(bos);

            //StreamUtil.flush(fos);

            StreamUtil.close(fos);

        }

    }

 

}

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public class StreamUtil {

    public static void flush(Flushable flushable) {

        if (flushable != null) {

            try {

                flushable.flush();

            catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

    public static void close(Closeable closeable){

        if(closeable!=null){

            try {

                closeable.close();

            catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

}

 4.下面是下载时的action

1

2

3

4

5

6

7

8

9

10

@RequestMapping(value = "/downloadVehicleRepair", method = RequestMethod.POST)

   public ResponseEntity<byte[]> download() throws IOException {

       String path = RuntimeEnvironmentUtil.getValue(SysConstent.code,SysConstent.path)+"\\VehicleRepairDetail.zip";

       File file = new File(path);

       HttpHeaders headers = new HttpHeaders();

       String fileName = new String("车辆维修清单.zip".getBytes("UTF-8"), "iso-8859-1");//为了解决中文名称乱码问题

       headers.setContentDispositionFormData("attachment", fileName);

       headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

       return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);

   }

 总结:以上只是关键代码。使用时只需要稍加改变就可以运行。

这篇关于大批量到处excel,防止内存溢出的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/985841

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

Mac excel 同时冻结首行和首列

1. 选择B2窗格 2. 选择视图 3. 选择冻结窗格 最后首行和首列的分割线加粗了就表示成功了

LeetCode--171 Excel表列序号

题目 给定一个Excel表格中的列名称,返回其相应的列序号。例如,A -> 1B -> 2C -> 3...Z -> 26AA -> 27AB -> 28 ... 示例 示例 1:输入: "A"输出: 1示例 2:输入: "AB"输出: 28示例 3:输入: "ZY"输出: 701 class Solution {public:int titleToNumber(strin

Android SurfaceFlinger——图形内存分配器(十一)

前面的文章中的图层合成器(HWC),这里我们接着看一下 SurfaceFlinger 中的另一个重要服务——图形内存分配器。 一、简介         android.hardware.graphics.allocator@2.0 是 Android 系统中硬件抽象层(HAL)的一个组件,专门用于图形内存的分配和管理。它是 SurfaceFlinger 在处理图形数据时所依赖的

浅谈 MySQL for excel

欢迎关注微信公众号“Python生态智联”  MySQL for excel是一个大小只有几兆的MySQL附件,它能让我们在Microsoft excel中处理MySQL数据。小编用了两天时间浏览了MySQL for excel的使用指南并按demo演示了一遍(手册地址https://dev.mysql.com/doc/mysql-for-excel/en/),现从功能和局限两方面对MySQL

逆向学习汇编篇:内存管理与寻址方式

本节课在线学习视频(网盘地址,保存后即可免费观看): ​​https://pan.quark.cn/s/3ceeb9ae6d98​​ 在汇编语言的世界中,内存管理和寻址方式是构建程序的基础。理解这些概念不仅对于编写高效的汇编代码至关重要,也是进行逆向工程分析的关键技能。本文将深入探讨内存管理的基本原则和多种寻址方式,并通过代码案例来展示它们的实际应用。 1. 内存管理 内存管理涉及如何分配

iOS 到处 ipa包的时候 会有四个选项分别代表什么

如图 在 iOS 到处 ipa包的时候 会有四个选项  1.Save for iOS App Store Deployment 保存到本地 准备上传App Store 或者在越狱的iOS设备上使用 2.Save for Ad Hoc Deployment 保存到本地 准备在账号添加的可使用设备上使用(具体为在开发者账户下添加可用设备的udid),该app包是发布证书编

Excel实用技巧——二级下拉菜单、数据验证

EXCEL系列文章目录   Excel系列文章是本人亲身经历职场之后萌发的想法,为什么Excel覆盖如此之广,几乎每个公司、学校、家庭都在使用,但是它深藏的宝藏功能却很少被人使用,PQ、BI这些功能同样适用于数据分析;并且在一些需要简单及时的数据分析项目前,Excel是完胜python、R、SPSS这些科学专业的软件的。因此决心开启Excel篇章。 数据分析为什么要学Excel Excel图表

段,页,段页,三种内存(RAM)管理机制分析

段,页,段页         是为实现虚拟内存而产生的技术。直接使用物理内存弊端:地址空间不隔离,内存使用效率低。 段 段:就是按照二进制文件的格式,在内存给进程分段(包括堆栈、数据段、代码段)。通过段寄存器中的段表来进行虚拟地址和物理地址的转换。 段实现的虚拟地址 = 段号+offset 物理地址:被分为很多个有编号的段,每个进程的虚拟地址都有段号,这样可以实现虚实地址之间的转换。其实所谓的地