最近在做項目功能時 ,發現有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);
}
總結:以上只是關鍵代碼。使用時只需要稍加改變就可以運行。
