JAVA导出数据到excel中大数据量的解决方法

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

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

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

导出成csv格式

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

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

	<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

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.以下是帮助类

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);
        }
    }

}

 

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

 @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);
    }

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

 

posted @ 2016-09-28 16:10  jason.bai  阅读(22624)  评论(3编辑  收藏  举报