POI에서 대량의 데이터를 내보내는 간단한 솔루션

39859 단어
설명: 내 컴퓨터 2.0CPU 2G 메모리는 10초에 20W 개의 데이터를 내보낼 수 있고, 12.8M의 excel 내용을 압축한 후 2.68M
우리는 POI에서 Excel을 내보낼 때 데이터의 양이 많으면 메모리가 넘치기 쉽다는 것을 안다.Excel의 sheet가 허용하는 최대 줄 수가 65536이기 때문에 우리는 sheet를 나누어 내보내려고 한다.그러나 이런 상황도 메모리가 넘치는 문제를 해결할 수 없다.데이터는 메모리에 한꺼번에 저장되어 있기 때문이다.이럴 때 excel을 여러 개 내보낼 수 있지 않을까요?다음은 excel을 여러 개 내보내는 대로 해볼게요.
우선: 우리는 데이터의 양이 얼마나 큰지 확인한 다음에 excel이 얼마나 많은 데이터를 내보내는지 확인해야 한다. 그러면 내보내는 Excel의 수량을 확정할 수 있기 때문에 우리는 순환적으로 excel을 내보내고 임의의 임시 디렉터리에 저장할 수 있다.이렇게 하면 메모리가 부족하면 가상 컴퓨터는 저장된 excel이 메모리에 있는 공간을 회수합니다.
만약 우리가 이미 여러 개의 excel을 성공적으로 생성했다고 가정한다면, 이때 우리는 어떻게 이 N개의 excel 문서를 클라이언트에게 전달합니까?사실 하나하나의 전송도 불가능한 것은 아니지만 사용자에게 그렇게 하는 것이 좋지 않다는 것을 고려하면 다시 여러 개의 파일이 네트워크에서 전송되는 것도 비교적 느리다.우리는 생성된 몇 개의 파일을 압축해서 클라이언트에게 전달하는 것을 고려할 수 있다.
요약 첫째, 차례로 excel 둘째, 압축 후 클라이언트로
 
다음은 제가 저의 작은 실례를 붙여서 참고하도록 하겠습니다.
 
첫째, Person.java 일반 javabean
 1 package bean;
 2 /**
 3  * 
 4  * @author 
 5  *
 6  */
 7 public class Person {
 8 
 9     private Integer id;
10     private String name;
11     private String address;
12     private String tel;
13     private Double money=0.0;
14     public Double getMoney() {
15         return money;
16     }
17     public void setMoney(Double money) {
18         this.money = money;
19     }
20     public Person(Integer id, String name, String address, String tel,Double money) {
21         super();
22         this.id = id;
23         this.name = name;
24         this.address = address;
25         this.tel = tel;
26         this.money=money;
27     }
28     public Integer getId() {
29         return id;
30     }
31     public void setId(Integer id) {
32         this.id = id;
33     }
34     public String getName() {
35         return name;
36     }
37     public void setName(String name) {
38         this.name = name;
39     }
40     public String getAddress() {
41         return address;
42     }
43     public void setAddress(String address) {
44         this.address = address;
45     }
46     public String getTel() {
47         return tel;
48     }
49     public void setTel(String tel) {
50         this.tel = tel;
51     }
52 }

 
둘째, Person Service는 100023개의 Person 객체를 생성하는 비즈니스 논리적 순환을 시뮬레이션합니다.
 
아날로그 업무 논리 코드
 1 package service;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import bean.Person;
 7 /**
 8  * 
 9  * @author 
10  *
11  */
12 public class PersonService {
13     public static List getPerson(){
14         List<Person> list =new ArrayList<Person>();
15         for(int i=0;i<100320;i++){
16             list.add(new Person(i,"zhangsan"+i," "+i,"13214587632",123123.12+i));    
17         }
18         return list;
19     }
20 
21 }

셋째, 비즈니스 처리 Servlet
 
servlet 코드 작업
  1 package servlet;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FileOutputStream;
  6 import java.io.IOException;
  7 import java.io.OutputStream;
  8 import java.text.SimpleDateFormat;
  9 import java.util.ArrayList;
 10 import java.util.Date;
 11 import java.util.List;
 12 
 13 import javax.servlet.ServletException;
 14 import javax.servlet.http.HttpServlet;
 15 import javax.servlet.http.HttpServletRequest;
 16 import javax.servlet.http.HttpServletResponse;
 17 
 18 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 19 import org.apache.poi.hssf.util.CellRangeAddress;
 20 import org.apache.poi.ss.usermodel.Cell;
 21 import org.apache.poi.ss.usermodel.CellStyle;
 22 import org.apache.poi.ss.usermodel.Row;
 23 import org.apache.poi.ss.usermodel.Sheet;
 24 import org.apache.poi.ss.usermodel.Workbook;
 25 
 26 import bean.Person;
 27 
 28 import service.PersonService;
 29 
 30 /**
 31  * 
 32  * @author http://javaflex.iteye.com/
 33  *
 34  */
 35 public class PersonServlet extends HttpServlet {
 36     private String fileName;
 37 
 38     public PersonServlet() {
 39         super();
 40     }
 41 
 42     public void destroy() {
 43         super.destroy(); // Just puts "destroy" string in log
 44         // Put your code here
 45     }
 46 
 47     public void doGet(HttpServletRequest request, HttpServletResponse response)
 48             throws ServletException, IOException {
 49         //  
 50         Date date = new Date();
 51         SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
 52         String f = "Person-" + format.format(date);
 53         this.fileName = f;
 54         setResponseHeader(response);
 55         OutputStream out = null;
 56         try {
 57             out = response.getOutputStream();
 58             List<Person> list = PersonService.getPerson();
 59             toExcel(list,request,10000,f,out);
 60         } catch (IOException e1) {
 61             e1.printStackTrace();
 62         } finally {
 63             try {
 64                 out.flush();
 65                 out.close();
 66             } catch (IOException e) {
 67                 e.printStackTrace();
 68             }
 69         }
 70     }
 71 
 72     /**   */
 73     public void setResponseHeader(HttpServletResponse response) {
 74         try {
 75             response.setContentType("application/octet-stream;charset=UTF-8");
 76             response.setHeader("Content-Disposition", "attachment;filename="
 77                     + java.net.URLEncoder.encode(this.fileName, "UTF-8")
 78                     + ".zip");
 79             response.addHeader("Pargam", "no-cache");
 80             response.addHeader("Cache-Control", "no-cache");
 81         } catch (Exception ex) {
 82             ex.printStackTrace();
 83         }
 84     }
 85     public void doPost(HttpServletRequest request, HttpServletResponse response)
 86             throws ServletException, IOException {
 87 
 88         doGet(request, response);
 89     }
 90     public void init() throws ServletException {
 91         // Put your code here
 92     }
 93 
 94     public void toExcel(List<Person> list, HttpServletRequest request,
 95             int length, String f, OutputStream out) throws IOException {
 96         List<String> fileNames = new ArrayList();//  s
 97         File zip = new File(request.getRealPath("/files") + "/" + f + ".zip");//  
 98         //  excel
 99         for (int j = 0, n = list.size() / length + 1; j < n; j++) {
100             Workbook book = new HSSFWorkbook();
101             Sheet sheet = book.createSheet("person");
102 
103             double d = 0;//  
104             String file = request.getRealPath("/files") + "/" + f + "-" + j
105                     + ".xls";
106 
107             fileNames.add(file);
108             FileOutputStream o = null;
109             try {
110                 o = new FileOutputStream(file);
111 
112                 // sheet.addMergedRegion(new
113                 // CellRangeAddress(list.size()+1,0,list.size()+5,6));
114                 Row row = sheet.createRow(0);
115                 row.createCell(0).setCellValue("ID");
116                 row.createCell(1).setCellValue("NAME");
117                 row.createCell(2).setCellValue("ADDRESS");
118                 row.createCell(3).setCellValue("TEL");
119                 row.createCell(4).setCellValue("Money");
120 
121                 int m = 1;
122 
123                 for (int i = 1, min = (list.size() - j * length + 1) > (length + 1) ? (length + 1)
124                         : (list.size() - j * length + 1); i < min; i++) {
125                     m++;
126                     Person user = list.get(length * (j) + i - 1);
127                     Double dd = user.getMoney();
128                     if (dd == null) {
129                         dd = 0.0;
130                     }
131                     d += dd;
132                     row = sheet.createRow(i);
133                     row.createCell(0).setCellValue(user.getId());
134                     row.createCell(1).setCellValue(user.getName());
135                     row.createCell(2).setCellValue(user.getAddress());
136                     row.createCell(3).setCellValue(user.getTel());
137                     row.createCell(4).setCellValue(dd);
138 
139                 }
140                 CellStyle cellStyle2 = book.createCellStyle();
141                 cellStyle2.setAlignment(CellStyle.ALIGN_CENTER);
142                 row = sheet.createRow(m);
143                 Cell cell0 = row.createCell(0);
144                 cell0.setCellValue("Total");
145                 cell0.setCellStyle(cellStyle2);
146                 Cell cell4 = row.createCell(4);
147                 cell4.setCellValue(d);
148                 cell4.setCellStyle(cellStyle2);
149                 sheet.addMergedRegion(new CellRangeAddress(m, m, 0, 3));
150             } catch (Exception e) {
151                 e.printStackTrace();
152             }
153             try {
154                 book.write(o);
155             } catch (Exception ex) {
156                 ex.printStackTrace();
157             } finally {
158                 o.flush();
159                 o.close();
160             }
161         }
162         File srcfile[] = new File[fileNames.size()];
163         for (int i = 0, n = fileNames.size(); i < n; i++) {
164             srcfile[i] = new File(fileNames.get(i));
165         }
166         util.FileZip.ZipFiles(srcfile, zip);
167         FileInputStream inStream = new FileInputStream(zip);
168         byte[] buf = new byte[4096];
169         int readLength;
170         while (((readLength = inStream.read(buf)) != -1)) {
171             out.write(buf, 0, readLength);
172         }
173         inStream.close();
174     }
175 }

마지막으로 도구 클래스 패키지 util이 있습니다.
 1 import java.io.FileInputStream;
 2 import java.io.FileOutputStream;
 3 import java.io.IOException;
 4 import java.util.zip.ZipEntry;
 5 import java.util.zip.ZipOutputStream;
 6 /**
 7  * 
 8  * @author http://javaflex.iteye.com/
 9  *
10  */
11 public class FileZip {
12     /**
13      * 
14      * @param srcfile  
15      * @param zipfile  
16      */
17     public static void ZipFiles(java.io.File[] srcfile, java.io.File zipfile) {
18         byte[] buf = new byte[1024];
19         try {
20             ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
21                     zipfile));
22             for (int i = 0; i < srcfile.length; i++) {
23                 FileInputStream in = new FileInputStream(srcfile[i]);
24                 out.putNextEntry(new ZipEntry(srcfile[i].getName()));
25                 int len;
26                 while ((len = in.read(buf)) > 0) {
27                     out.write(buf, 0, len);
28                 }
29                 out.closeEntry();
30                 in.close();
31             }
32             out.close();
33         } catch (IOException e) {
34             e.printStackTrace();
35         }
36     }
37 }

최적화: (일부 사람들의 관점, 참고) ---poi 빅데이터의 페이지별 빅데이터 양이 병발하는 문제는 카드가 죽는다.poi3.8은 메모리 방출을 제한할 수 있지만 2003xls 형식은 지원되지 않습니다.압축 패키지 내보내기가 가장 좋습니다.빅데이터 양의 가져오기 내보내기 데이터는 일반적으로 텍스트 형식의 중개 저장소를 사용하기 때문에 excel로 내보낼 필요가 없다.데이터베이스에서 20W 데이터를 한꺼번에 읽는 것이 아니라 페이지별로 excel에 써야 한다.

좋은 웹페이지 즐겨찾기