求助~~~关于jxl写大批量数据的Excel

clementxr 2012-01-20 10:29:29
对于jxl不是很熟悉,简单的写了个读文件出excel的程序。
但是现在这样做法一旦数据量太大,缓存就爆掉了。请教大牛怎么样才能实现读取一部分数据,先写入Excel,然后再读一部分再写进去。
当然有更好的方法就最好了~

package jxl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

public class JxlExcelWriter {

/**
* @param out 输出excel文件.
* @param br 输入txt文件.
*/
public void writeExcel(OutputStream out, BufferedReader br) {
if(br == null) {
throw new IllegalArgumentException("写excel流需要file!");
}
try {
WritableWorkbook workbook = Workbook.createWorkbook(out);
WritableSheet ws = workbook.createSheet("sheet 1", 0);
int rowNum = 0; // 写入行数

//文件行数
String line = null;
while((line = br.readLine()) != null){
String[] data = line.split("\t");
Object[] cells = (Object[]) data;
putRow(ws, rowNum, cells); // 写一行到sheet
rowNum++;

}

workbook.write();
workbook.close(); // 关闭、保存Excel

System.out.print("success!");
} catch (RowsExceededException e) {
System.out.println("jxl write RowsExceededException: "+e.getMessage());
} catch (WriteException e) {
System.out.println("jxl write WriteException: "+e.getMessage());
} catch (IOException e) {
System.out.println("jxl write file i/o exception!, cause by: "+e.getMessage());
}
}

private void putRow(WritableSheet ws, int rowNum, Object[] cells) throws RowsExceededException, WriteException {

for(int i=0; i<cells.length; i++) {
Label cell = new Label(i, rowNum, ""+cells[i]);
ws.addCell(cell);
}
}

public static void main(String args[]) {

try {
BufferedReader br = new BufferedReader(new FileReader("e:/input/data.txt"));
OutputStream out = new FileOutputStream(new File("e:/out/test.xls"));

JxlExcelWriter jxlExcelWriter = new JxlExcelWriter();
jxlExcelWriter.writeExcel(out, br);
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

...全文
360 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
luozhenquan 2012-06-01
  • 打赏
  • 举报
回复
有个可以优化的思路,不过实现起来有点麻烦,可以参考一下,如下:
1:把所有的数据按5万进行分组(如25万则分成5组)
2:把每组分别写到一个.txt文件中(如25万就是5个txt文件)
3:遍历生成的txt文件,每次只读取一个文件,用来写excel文件,每个文件写一个表,写完关闭(5个txt文件,最终返回给用户的是具有5个表的excel文件

这样的做法,原理上是可以减少内存的损耗的。。。。。
luozhenquan 2012-06-01
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]
无论是jxl还是poi都做不到楼主说的功能。
就算实现了,也属于“假分页”,因为你说你想分批写,也是要把数据load进内存的,这两个框架都无法分sheet(真正的写完后清内存数据)的。

不过,我们可以换位思考一下,一个excel, 65535行,如果真的写满了,谁去看呀?

这种需求就属于技术的bottleneck了,需要分excel写,即N条数据,按65535行数据为一个xls文件,……
[/Quote]

其实在实际应用中,导出6万多数据是好正常的需求来的,因为这些数据不是用来看,而是用来分析,我做过的一个项目中,就有要求导出30万以上的数据。。。。
luozhenquan 2012-06-01
  • 打赏
  • 举报
回复
jxl写入多少都没有关系,我试过24M的都可以(24万多行),我的做法是把所有的数据放到数组中,每5万写一个sheet
/**
* 写数据
*
* @param sheet
* @param data
* 数据;
* @param row
* 行数(表示数据写入的目标行);
* @throws WriteException
* @throws RowsExceededException
*/
private static void writeData(WritableSheet sheet, String[] data, int row)
throws RowsExceededException, WriteException {
for (int i = 0; i < data.length; i++) {
Label label = new Label(i, row, data[i], dateFormat);
sheet.addCell(label);
}
}

不过这样写法比较耗损内存的,应该有优化的方法
clementxr 2012-01-20
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 lxwankkk 的回复:]

引用 4 楼 huang_1106 的回复:

引用 3 楼 lxwankkk 的回复:

引用 2 楼 huang_1106 的回复:

引用 1 楼 lxwankkk 的回复:

Object[] cells = (Object[]) data;
这数组爆了?

我用poi的处理方法是sheet row cell都是有一个就new一个,然后才插入,而不是先放入数组。
……
[/Quote]

我因为是新手,最近也没事,正好几个前辈碰到这个问题手头又忙就让我研究一下,他们本来用poi的解决不了,让我看看jxl有没有可能解决。数据的话项目里肯定是有格式要求的,但我现在只是为了研究这个问题,所以程序尽量简化,达到这个效果就好了。
还有前面的不是数组爆的,因为数组里存放的只是一行的数据,不会出问题。只是读一行写一行,到最后统一write到Excel里面,这中间貌似是放缓存的,然后就出问题了。
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 huang_1106 的回复:]

引用 3 楼 lxwankkk 的回复:

引用 2 楼 huang_1106 的回复:

引用 1 楼 lxwankkk 的回复:

Object[] cells = (Object[]) data;
这数组爆了?

我用poi的处理方法是sheet row cell都是有一个就new一个,然后才插入,而不是先放入数组。
像03版本前的excel文件sheet单表最大是65……
[/Quote]
不知你的需求是什么,这样处理好不好。呵呵,毕竟这么大的数据量,生成的excel文件,如果查看时不管是写宏还是别的来处理都是要再做一次才好查看吧。不知能否按条件,分门别类的导出更好一点。
clementxr 2012-01-20
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 lxwankkk 的回复:]

引用 2 楼 huang_1106 的回复:

引用 1 楼 lxwankkk 的回复:

Object[] cells = (Object[]) data;
这数组爆了?

我用poi的处理方法是sheet row cell都是有一个就new一个,然后才插入,而不是先放入数组。
像03版本前的excel文件sheet单表最大是65535行,那就在行数进行判断,如果多于一个数,比……
[/Quote]

嗯,再去研究看看,头疼啊
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 huang_1106 的回复:]

引用 1 楼 lxwankkk 的回复:

Object[] cells = (Object[]) data;
这数组爆了?

我用poi的处理方法是sheet row cell都是有一个就new一个,然后才插入,而不是先放入数组。
像03版本前的excel文件sheet单表最大是65535行,那就在行数进行判断,如果多于一个数,比如5W,那么就new一个新的sheet。这样创建过5……
[/Quote]
= =!我得试试我这里10M上的行么,不过应该可以,因为我没使用数组,也就不是先把数据放到内存中。
你重写一个putRow方法看看呢?txt里读出数据,然后直接放入cell,得到数据时还可以添加判断类型等之类的功能什么的
clementxr 2012-01-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lxwankkk 的回复:]

Object[] cells = (Object[]) data;
这数组爆了?

我用poi的处理方法是sheet row cell都是有一个就new一个,然后才插入,而不是先放入数组。
像03版本前的excel文件sheet单表最大是65535行,那就在行数进行判断,如果多于一个数,比如5W,那么就new一个新的sheet。这样创建过5-6M的Excel文件也没问题。
jxl应该也……
[/Quote]

应该是存放入row的时候爆掉了,我现在出的Excel最大能9M多,但要是数据量再大一点就不行了
  • 打赏
  • 举报
回复
Object[] cells = (Object[]) data;
这数组爆了?

我用poi的处理方法是sheet row cell都是有一个就new一个,然后才插入,而不是先放入数组。
像03版本前的excel文件sheet单表最大是65535行,那就在行数进行判断,如果多于一个数,比如5W,那么就new一个新的sheet。这样创建过5-6M的Excel文件也没问题。
jxl应该也可以这么处理吧
clementxr 2012-01-20
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 lifetragedy 的回复:]

无论是jxl还是poi都做不到楼主说的功能。
就算实现了,也属于“假分页”,因为你说你想分批写,也是要把数据load进内存的,这两个框架都无法分sheet(真正的写完后清内存数据)的。

不过,我们可以换位思考一下,一个excel, 65535行,如果真的写满了,谁去看呀?

这种需求就属于技术的bottleneck了,需要分excel写,即N条数据,按65535行数据为一个xls文件……
[/Quote]

嗯,我也只是试着去研究一下,无论成不成功都算有收获嘛。
鉴于您专业的知识,还是非常感谢~~
TGITCIC 2012-01-20
  • 打赏
  • 举报
回复
无论是jxl还是poi都做不到楼主说的功能。
就算实现了,也属于“假分页”,因为你说你想分批写,也是要把数据load进内存的,这两个框架都无法分sheet(真正的写完后清内存数据)的。

不过,我们可以换位思考一下,一个excel, 65535行,如果真的写满了,谁去看呀?

这种需求就属于技术的bottleneck了,需要分excel写,即N条数据,按65535行数据为一个xls文件,写完后立望施放,然后再把剩余的数据写到另一个xls文件。

否则根本无法做到,因此需要从需求上去优化这个功能了。
clementxr 2012-01-20
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 lxwankkk 的回复:]

引用 10 楼 huang_1106 的回复:

引用 8 楼 lxwankkk 的回复:

读取的txt文件太大了
应该还是考虑别的方法写入吧,我也是新手,呵呵,具体也没操作过~~~
那你卡死的这个程序创建出的excel文件有多少数据?


多少行不一定的,看每行的数据大小。
现在能处理的txt文件最大差不多位1900k左右
就是想上来问问有没有别的方法写入或者优化一下
……
[/Quote]

谢谢~~可惜没人进来啊- -
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 huang_1106 的回复:]

引用 8 楼 lxwankkk 的回复:

读取的txt文件太大了
应该还是考虑别的方法写入吧,我也是新手,呵呵,具体也没操作过~~~
那你卡死的这个程序创建出的excel文件有多少数据?


多少行不一定的,看每行的数据大小。
现在能处理的txt文件最大差不多位1900k左右
就是想上来问问有没有别的方法写入或者优化一下
[/Quote]
呵呵,帮顶下吧 等高手来了~~
clementxr 2012-01-20
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 lxwankkk 的回复:]

读取的txt文件太大了
应该还是考虑别的方法写入吧,我也是新手,呵呵,具体也没操作过~~~
那你卡死的这个程序创建出的excel文件有多少数据?
[/Quote]

多少行不一定的,看每行的数据大小。
现在能处理的txt文件最大差不多位1900k左右
就是想上来问问有没有别的方法写入或者优化一下
clementxr 2012-01-20
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 lxwankkk 的回复:]

[/Quote]

嗯,这些细节以后注意。但是并不会影响运行的结果额。。
  • 打赏
  • 举报
回复
读取的txt文件太大了
应该还是考虑别的方法写入吧,我也是新手,呵呵,具体也没操作过~~~
那你卡死的这个程序创建出的excel文件有多少数据?
  • 打赏
  • 举报
回复

public static void main(String args[]) {

try {
BufferedReader br = new BufferedReader(new FileReader("e:/input/data.txt"));
OutputStream out = new FileOutputStream(new File("e:/out/test.xls"));

JxlExcelWriter jxlExcelWriter = new JxlExcelWriter();
jxlExcelWriter.writeExcel(out, br);
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

中午歇了会,呵呵
br没有关闭吧= =~~~
关闭流的操作写到finally里比较好

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧