在Java Web开发中,经常需要导出大量的数据到Excel,使用POI、JXL直接生成Excel,很容易就造成内存溢出了。
1、有一种方式,就是把数据写成csv格式文件。
1)csv文件可以直接用Excel打开。
2)写csv文件的效率和写txt文件的效率一样高。
3)同样的数据内容,生成的csv文件的大小远远小于生成的Excel文件。
从以上优点就可以看出生成csv文件消耗的内存绝对小于生成Excel文件。
2、按一定的格式去生成csv文件,在Excel中打开的时候就是完整的行和列格式。
例如:在Excel中的格式:
那么,在csv文件中格式就必须为:
就是说,列和列之间,需要用英文输入法状态下的逗号","间隔:风云第一刀,古龙。
3、在Struts2中导出数据到Excel,一个简单的例子。
CsvAction,生成csv文件,并且将生成的csv文件完整路径传递到下载Action。
package
cn.luxh.struts2.action;
import
java.io.FileWriter;
import
java.io.IOException;
import
java.text.SimpleDateFormat;
import
java.util.ArrayList;
import
java.util.Date;
import
java.util.List;
import
cn.luxh.struts2.entity.Novel;
import
com.opensymphony.xwork2.ActionSupport;
public
class
CsvAction
extends
ActionSupport
{
private
static
final
long
serialVersionUID
=
-2862629695443964658L;
private
String
fileName;
public
String
exportData2CSV()
{
List<Novel>
novels
=
getNovels();
fileName
=
"D:/novels.csv";
writeData2CSV(novels,fileName);
return
SUCCESS;
}
private
List<Novel>
getNovels()
{
List<Novel>
novels
=
new
ArrayList<Novel>();
Novel
novel1
=
new
Novel("风云第一刀","古龙",
new
Date());
Novel
novel2
=
new
Novel("书剑恩仇录","金庸",
new
Date());
Novel
novel3
=
new
Novel("陆小凤传奇","古龙",
new
Date());
Novel
novel4
=
new
Novel("鹿鼎记","金庸",
new
Date());
novels.add(novel1);
novels.add(novel2);
novels.add(novel3);
novels.add(novel4);
return
novels;
}
public
void
writeData2CSV(List<Novel>
novels,String
fileName)
{
FileWriter
fw
=
null;
try
{
fw
=
new
FileWriter(fileName);
//
输出标题头
//
注意列之间用","间隔,写完一行需要回车换行"\r\n"
String
title
=
"序号,小说名称,作者,出版日期\r\n";
fw.write(title);
String
content
=
null;
SimpleDateFormat
sdf
=
new
SimpleDateFormat("yyyy-MM-dd");
for(
int
i=0;i<novels.size();i++)
{
Novel
novel
=
novels.get(i);
//
注意列之间用","间隔,写完一行需要回车换行"\r\n"
content
=(i+1)+","+novel.getName()+","+novel.getAuthor()+","+sdf.format(novel.getPublishDate())+"\r\n";
fw.write(content);
}
}
catch(Exception
e)
{
e.printStackTrace();
throw
new
RuntimeException(e);
}
finally
{
try
{
if(fw!=
null)
{
fw.close();
}
}
catch
(IOException
e)
{
e.printStackTrace();
}
}
}
}
配置文件:
<!--
将csv文件路径传递到公共的下载Action进行下载
-->
<
action
name
="exportData2CSV"
class
="cn.luxh.struts2.action.CsvAction"
method
="exportData2CSV"
>
<
result
type
="redirectAction"
>
<
param
name
="actionName"
>download
</
param
>
<
param
name
="nameSpace"
>/download
</
param
>
<!--
附件的完整路径 ,传递给下载Action
-->
<
param
name
="fileName"
>${fileName}
</
param
>
</
result
>
</
action
>
提供下载功能的Action参考http://www.cnblogs.com/luxh/archive/2012/07/01/2571778.html
4、看一下同样的数据内容,csv文件和Excel文件的大小对比:
导出excel确实有些麻烦,不能流式处理,导致占用比较大的内存,很容易导致内存溢出;并且excel的数据量是有限制的,不能超过65536行。
一旦超过,将无法生成excel文件。
用csv方式导出,则可以像导出txt一样,以文本流的方式进行流式处理,不但能导出海量信息,而且流式处理占用内存极低,服务器对浏览器的响应也是非常迅速的。轻松导出几百万行数据,理论上是不限量的。
不过,csv方式导出也存在问题:
首先,如果用excel来打开csv,超过65536行的数据都会看不见,这是excel程序的问题。
其次,如果你要导出一个身份证号码,手机号码,邮政编码等,纯数字构成的字符串,在excel中打开csv时,这些字段很容易被识别成数字,造成误解。
解决方法是在字符串前加“'”(单引号),然而这样处理后,excel打开scv时会看到这个“'”,又不对了,并且单击该单元格再离开后,这个单引号会自动消失,这是'在excel中的特殊用途导致的,如果此时再保存文件,文件中的'会丢失,如果再打开该csv文件,问题就更严重了,编码全成数字了(因为'丢了)!
看来这也是excel的问题。
上面两个问题按下不说的话,那么csv文件还是有些基本规则的,比如用""括起来那么里面的","不会作为分隔符等转义操作。
总体而言,我也倾向于csv格式,它可以流式处理。
注意:本内容是转载,原地址:http://blog.sina.com.cn/s/blog_8887f2c3010114vq.html