簡體   English   中英

將海量數據寫入excel文件的Java最佳方法

[英]java best way to write huge data to excel file

我在2個PostgreSQL數據庫中有大量數據,我想將其寫入excel文件,我的代碼工作得很好,但是問題是需要很長時間。 另外,當我選擇數據周期超過3個月時,服務器中將出現“ Java堆空間”錯誤,因為它多於200萬行。 我需要一種更有效的方式將數據寫入excel文件,而且timestamp列需要在寫入文件之前將其更改為DateTime列。 我將文件制作為服務器,然后將文件路徑返回到客戶端以進行下載。

請編寫示例代碼來解決我的問題。

public String exportRmsValues(String path, String query, String query2) {
    System.out.println(query);
    System.out.println(query2);
    dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    Calendar cal = Calendar.getInstance();
    System.out.println("start exportRmsValues \n" + dateFormat.format(cal.getTime()));
    Connection c = null;
    Statement st = null;
    Connection c2 = null;
    Statement st2 = null;

    XSSFWorkbook wb = new XSSFWorkbook();
    XSSFSheet sheet = wb.createSheet("RMS Data Sheet 1");
    XSSFSheet sheet2 = wb.createSheet("RMS Data Sheet 2");
    XSSFSheet sheet3 = wb.createSheet("RMS Data Sheet 3");
    //XSSFCellStyle my_style = wb.createCellStyle();
    //XSSFFont my_font = wb.createFont();
    //my_font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
    //my_style.setFont(my_font);

    Row rowhead = sheet.createRow(0);       
    rowhead.createCell(0).setCellValue("Va");
    rowhead.createCell(1).setCellValue("Vb");
    rowhead.createCell(2).setCellValue("Vc");
    rowhead.createCell(3).setCellValue("Ia");
    rowhead.createCell(4).setCellValue("Ib");
    rowhead.createCell(5).setCellValue("Ic");
    rowhead.createCell(6).setCellValue("datatime");

    Row rowhead2 = sheet2.createRow(0);     
    rowhead2.createCell(0).setCellValue("Va");
    rowhead2.createCell(1).setCellValue("Vb");
    rowhead2.createCell(2).setCellValue("Vc");
    rowhead2.createCell(3).setCellValue("Ia");
    rowhead2.createCell(4).setCellValue("Ib");
    rowhead2.createCell(5).setCellValue("Ic");
    rowhead2.createCell(6).setCellValue("datatime");

    Row rowhead3 = sheet3.createRow(0);     
    rowhead3.createCell(0).setCellValue("Va");
    rowhead3.createCell(1).setCellValue("Vb");
    rowhead3.createCell(2).setCellValue("Vc");
    rowhead3.createCell(3).setCellValue("Ia");
    rowhead3.createCell(4).setCellValue("Ib");
    rowhead3.createCell(5).setCellValue("Ic");
    rowhead3.createCell(6).setCellValue("datatime");

    try {
        Class.forName("org.postgresql.Driver");
        String conString = "jdbc:postgresql://" + host + ":" + port + "/" + DBName
                + "?user=" + user + "&pass=" + pass;
        String conString1 = "jdbc:postgresql://" + host + ":" + port2 + "/" + DBName2
                + "?user=" + user + "&pass=" + pass;
        c = DriverManager.getConnection(conString);
        c2 = DriverManager.getConnection(conString1);
        st = c.createStatement();
        st2 = c2.createStatement();
        String file_name = "RMS_"+dateFormat2.format(cal.getTime())+".xlsx";
        //path = "/opt/jetty/files/"+file_name;
        path = path + file_name;
        List<ResultSet> resultSets = new ArrayList<>();
        resultSets.add(st.executeQuery(query));
        resultSets.add(st2.executeQuery(query2));
        ResultSets rs = new ResultSets(resultSets);
        int index = 1; // row index 0 for columns name
        int index2 = 1;
        int index3 = 1;
        int sheetCount = 1;
        Row row = null;
        Calendar calendar = Calendar.getInstance();
        //TimeZone tz = TimeZone.getDefault();
        while (rs.next()) {
            //XSSFRow row = sheet.createRow((long) index);
            if ( sheetCount <= 1000000 ) {
                row = sheet.createRow(index);
                index++;
            }
            if ( sheetCount > 1000000 && sheetCount <= 2000000) {
                row = sheet2.createRow(index2);
                index2++;
            }
            if ( sheetCount > 2000000 && sheetCount <= 3000000) {
                row = sheet3.createRow(index3);
                index3++;
            }

            /*else {
                row = sheet2.createRow(index2);
                index2++;
                if ( sheetCount >= 2000000 ) {
                    row = sheet3.createRow(index3);
                    index3++;
                }
            }*/

            row.createCell(0).setCellValue(rs.getDoubleValues("va"));
            row.createCell(1).setCellValue(rs.getDoubleValues("vb"));
            row.createCell(2).setCellValue(rs.getDoubleValues("vc"));
            row.createCell(3).setCellValue(rs.getDoubleValues("ia"));
            row.createCell(4).setCellValue(rs.getDoubleValues("ib"));
            row.createCell(5).setCellValue(rs.getDoubleValues("ic"));
            long datatime = rs.getLongValues("datatime");
            calendar.setTimeInMillis(datatime * 1000);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date currenTimeZone = (Date) calendar.getTime();
            row.createCell(6).setCellValue(sdf.format(currenTimeZone));
            sheetCount++;
        }

        FileOutputStream fileOut = new FileOutputStream(path);
        wb.write(fileOut);
        fileOut.close();
        System.out.println("Data is saved in excel file.");
        rs.close();
        st.close();
        c.close();
        st2.close();
        c2.close();
    } catch (Exception e) {
        System.out.println(e);
        e.printStackTrace();
    }
    Calendar cal1 = Calendar.getInstance();
    System.out.println("finish exportRmsValues \n" + dateFormat.format(cal1.getTime()));
    return path;
}

我有好的方法而且很快

query = "select name, to_timestamp(datatime) from x ";
CopyManager copyManager = new CopyManager((BaseConnection) c);
File file = new File(path);
FileOutputStream fileOutputStream = new FileOutputStream(file);

//and finally execute the COPY command to the file with this method:

copyManager.copyOut("COPY (" + query + ") TO STDOUT WITH (FORMAT CSV)", fileOutputStream);

這會將查詢中的所有數據寫入CSV文件。

您可以使用BCP Utility來實現。 命令行查詢只是將查詢返回的數據復制為所需格式而已。 在計算機上安裝BCP實用程序后,運行以下代碼片段:

public class ExcelExport {

    public static void main(String[] args) {

        String excelFileName = "excel/myExcelFile.xls";  // Other formats also supported like .csv, .xlsx etc
        String query = "The SQL Query goes here";
        String databaseName = "DatabseName";
        String ServerUrl = "DatabaseServerUrl/IP";
        String userName = "DatabaseUsername";
        String password = "DatabasePassword";
        String bcpCommand = "bcp \"" + query + "\" queryout \"" + excelFileName + "\" -c -d \"" + databaseName
                + "\" -S " + ServerUrl + " -U \"" + userName + "\" -P \"" + password + "\"";
        System.out.println("BCP Command : " + bcpCommand);

        // Executes BCP command using command line
        ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", bcpCommand);

        try {

            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;

            while (true) {
                line = reader.readLine();

                if (line == null) {
                    break;
                }

                System.out.println(line);
            }

            System.out.println("Excel File Created !!!");

        } catch (IOException ioException) {
            ioException.printStackTrace();
            System.out.println("Failed to export data to excel !!!");
        }
    }
}

注意:它不能像Apache POI一樣很好地格式化excel文件,但是要導出數百萬個數據。 這樣可以節省大量時間。 您可以手動進行格式化。 該代碼復制查詢返回的所有數據。 因此,請記住,您的記錄數不應超過excel文件的行限制,即當前版本為1,048,576行,Office 2003之前為65536行。因此,對於200萬行,如果需要,可以創建多個文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM