千百万级别数据导出核心代码
抓核心:导出效率 + 导出形式
解释: 导出效率:线程、 导出形式:压缩包
示例
// 第一步:创建压缩包输出流 File dir = new File(path); if (!dir.exists()) { if (!dir.mkdirs()) { } } String filePath = path + "文件名"; File file = new File(filePath); ZipOutputStream outputStream = null; if (!file.exists()) { file.createNewFile(); } outputStream = new ZipOutputStream(new FileOutputStream(file));
// 第二步: 数据压缩 // 数据总量 int total = "数据总量" // 单文件总数据量 2<<11 = 2的12次方 Integer pageSize = 2<<11; // 数据分页 int pageTotal = total % pageSize == 0 ? total/ pageSize : total / pageSize + 1; // 注意: 这里pageSize 和 pageSize 配合数据库分页查询使用 // 计量 CountDownLatch countDownLatch = new CountDownLatch(pageTotal); for (int i = 1; i <= pageTotal; i++) { // 自己实现PoiExportTask类 实现Runable接口 run方法里面放入生成excel逻辑以及将excel文件放入压缩输出流中 PoiExportTask<JSONObject> task = new PoiExportTask<>(); task.setColumns(columnList);//columnList: List<ExcelUtil.ExcelColumn> excel 表头 task.setData(list);//list : 数据库分页查询 task.setCountDownLatch(countDownLatch); task.setZipOutputStream(zipOutputStream); task.setIndexStr("["+(i - 1) * pageSize+"-"+((i - 1) * pageSize + pageSize)+"]"); new Thread(task,"exportWithMultiThreadByPoi-"+i).start(); } countDownLatch.await(); zipOutputStream.close();
// 第二步中,如何将excel放入zipoutstream压缩输出流中 if (workbook instanceof HSSFWorkbook) { //这里只是声明文件路径和名称 filePath = filePath+"_"+index + ".xls"; } else { filePath = filePath+"_"+index + ".xlsx"; } try { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); workbook.write(outputStream); //读取数据 InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); zipOutputStream.putNextEntry(new ZipEntry(filePath)); int len; byte[] buf = new byte[1024]; while ((len = inputStream.read(buf)) > 0) { zipOutputStream.write(buf, 0, len); } outputStream.flush(); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } finally { if(zipOutputStream != null) { try { zipOutputStream.closeEntry(); } catch (IOException e) { e.printStackTrace(); } } }