首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 高效導出 CSV:反射通用工具類、GBK 編碼兼容 Excel、百萬級數據秒級生成

     編輯:Java 綜合教學

CSV 本質與優勢

  • 純文本,逗號分隔,Excel 可直接開啟
  • 無 POI 對象樹開銷,記憶體佔用極低,適合大數據導出
  • 流式寫入,邊查邊寫,避免 OOM

通用導出工具類

public class CsvUtil {
    public static  void exportCsv(
            String[] headers,           // 表頭
            String[] fields,            // 實體屬性名,與 headers 一一對應
            List dataList,           // 數據源
            OutputStream out,           // 輸出流(HttpServletResponse.getOutputStream())
            String charset              // 建議 "GBK" 兼容中文 Excel
    ) throws IOException, IllegalAccessException {
        try (OutputStreamWriter writer = new OutputStreamWriter(out, charset)) {
            // 1. 寫表頭
            for (int i = 0; i < headers.length; i++) {
                writer.write(headers[i]);
                if (i < headers.length - 1) writer.write(',');
            }
            writer.write("\r\n");

            // 2. 反射寫數據
            for (T obj : dataList) {
                for (int i = 0; i < fields.length; i++) {
                    String fieldName = fields[i];
                    try {
                        Field field = obj.getClass().getDeclaredField(fieldName);
                        field.setAccessible(true);
                        Object val = field.get(obj);
                        writer.write(val != null ? val.toString() : "");
                    } catch (NoSuchFieldException e) {
                        writer.write(""); // 屬性不存在留空
                    }
                    if (i < fields.length - 1) writer.write(',');
                }
                writer.write("\r\n");
            }
            writer.flush();
        }
    }
}

Controller 整合範例

@GetMapping("/export/users.csv")
public void exportUsers(HttpServletResponse response) throws IOException {
    List users = userService.findAll(); // 或分頁流式查詢
    response.setContentType("text/csv;charset=GBK");
    response.setHeader("Content-Disposition", "attachment;filename=users_" + System.currentTimeMillis() + ".csv");
    String[] headers = {"ID", "用戶名", "郵箱", "建立時間"};
    String[] fields = {"id", "username", "email", "createTime"};
    CsvUtil.exportCsv(headers, fields, users, response.getOutputStream(), "GBK");
}

百萬級優化建議

  1. 流式查詢:MyBatis @Select + ResultHandler 或 Cursor,避免一次性載入 List
  2. 分批寫入:每 1000 條 flush 一次,減少 GC 壓力
  3. 異步導出:大文件提交任務 → 後台生成 → WebSocket/郵件通知下載
  4. 字段預編譯:啟動時緩存 Field[],避免每行反射 getDeclaredField

常見坑點

  • 字段包含逗號/換行/雙引號 → 需用雙引號包裹並轉義雙引號(RFC 4180)
  • Excel 打開 CSV 自動科學計數法(長數字/身份證) → 字段前加 \t 或改用 xlsx
  • UTF-8 BOM 導致 Excel 亂碼 → 輸出流寫入 new byte[]{(byte)0xEF, (byte)0xBB, (byte)0xBF} 或改用 GBK
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved