您的位置:首页 > 大数据

java导出dbf文件大数据量的处理方法

2012-12-05 14:30 645 查看

1,用到的jar包:javadbf.jar。

2,如果是小数据量的导出,用普通的方法就可以。

用JavaDBF操作(读、写)DBF文件<o:p></o:p>

最近的一个项目需要动态生成DBF文件,用到JavaDBF,简单介绍一下<o:p></o:p>

官方网站:http://javadbf.sarovar.org/<o:p></o:p>

官方英文指南:http://sarovar.org/docman/view.php/32/23/javadbf-tutorial.html<o:p></o:p>

最新版本:<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">0.4.0</st1:chsdate>,最后发布时间还是在<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="1" month="4" year="2004">2004年4月1日</st1:chsdate>,看来DBF真是老了。老归老,有些时候还是得用。<o:p></o:p>

下面是分别是读取和写DBF文件以及其他操作函数(关键信息的解释我放在了注释里,这样看起来会更方便):<o:p></o:p>

读取DBF文件:<o:p></o:p>

<o:p>

java 代码

public static void readDBF(String path)

{

InputStream fis = null;
try
{
//读取文件的输入流
fis = new FileInputStream(path);
//根据输入流初始化一个DBFReader实例,用来读取DBF文件信息
DBFReader reader = new DBFReader(fis);
//调用DBFReader对实例方法得到path文件中字段的个数
int fieldsCount = reader.getFieldCount();
//取出字段信息
for( int i=0; i<fieldsCount; i++)

{
DBFField field = reader.getField(i);
System.out.println(field.getName());
}
Object[] rowValues;
//一条条取出path文件中记录
while((rowValues = reader.nextRecord()) != null)
{
for( int i=0; i<rowValues.length; i++)
{
System.out.println(rowValues[i]);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{
fis.close();
}catch(Exception e){}
}
}

写DBF文件:

java 代码

public static void writeDBF(String path)

OutputStream fos = null;
try
{
//定义DBF文件字段
DBFField[] fields = new DBFField[3];
//分别定义各个字段信息,setFieldName和setName作用相同,
//只是setFieldName已经不建议使用
fields[0] = new DBFField();
//fields[0].setFieldName("emp_code");
fields[0].setName("semp_code");
fields[0].setDataType(DBFField.FIELD_TYPE_C);
fields[0].setFieldLength(10);

fields[1] = new DBFField();
//fields[1].setFieldName("emp_name");
fields[1].setName("emp_name");
fields[1].setDataType(DBFField.FIELD_TYPE_C);
fields[1].setFieldLength(20);

fields[2] = new DBFField();
//fields[2].setFieldName("salary");
fields[2].setName("salary");
fields[2].setDataType(DBFField.FIELD_TYPE_N);
fields[2].setFieldLength(12);
fields[2].setDecimalCount(2);

//DBFWriter writer = new DBFWriter(new File(path));

//定义DBFWriter实例用来写DBF文件
DBFWriter writer = new DBFWriter();
//把字段信息写入DBFWriter实例,即定义表结构
writer.setFields(fields);
//一条条的写入记录
Object[] rowData = new Object[3];
rowData[0] = "1000";
rowData[1] = "John";
rowData[2] = new Double(5000.00);
writer.addRecord(rowData);

rowData = new Object[3];
rowData[0] = "1001";
rowData[1] = "Lalit";
rowData[2] = new Double(3400.00);

writer.addRecord(rowData);

rowData = new Object[3];
rowData[0] = "1002";
rowData[1] = "Rohit";
rowData[2] = new Double(7350.00);

writer.addRecord(rowData);

//定义输出流,并关联的一个文件
fos = new FileOutputStream(path);
//写入数据
writer.write(fos);

//writer.write();
}catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{
fos.close();
}catch(Exception e){}
}

注意:writer.addRecord(rowData)时并不真正写入数据,在最后writer.write(fos)时才会把数据写入DBF文件,之前addRecord的数据暂时存放在内存中。如果数据量过大,这种方式显然不适合,内存中存储的数据过多,所以JavaDBF提供了另外一种机制来解决这个问题:Sync Mode(同步模式)。使用方法如下:

用new DBFWriter(new File(path))实例化DBFWriter类,最后写入数据时用writer.write(),这样在每次addRecord时数据就被写入的DBF文件中。

因为初始化DBFWriter时传递了DBF文件,所以不用再定义DBF表结构,如果你定义并加载表结构会报异常。

下面这个函数会根据你传入的数据信息自动生成DBF文件,这样以后我们只要构造好数组,就可以直接得到DBF文件,不用每次都去写重复的代码。

java 代码

public static void generateDbfFromArray(HttpServletResponse response,
String dbfName, String[] strutName,byte[] strutType,
int[] strutLength, Object[][] data){

OutputStream fos = null;
try
{
dbfName = new String(dbfName.getBytes("gbk"), "ISO-8859-1");
response.setContentType("applicationnd.ms-excel");
response.setHeader("Content-disposition", "attachment; filename=" + dbfName + ".dbf");
fos = response.getOutputStream();
int fieldCount = strutName.length;
DBFField[] fields = new DBFField[fieldCount];
for(int i=0;i<fieldCount;i++)
{
fields[i] = new DBFField();
fields[i].setName(strutName[i]);
fields[i].setDataType(strutType[i]);
//Date类型不能设置字段长度,这里没有处理其它没有字段长度的类型
if(strutType[i] != DBFField.FIELD_TYPE_D){
fields[i].setFieldLength(strutLength[i]);
}
}

DBFWriter writer = new DBFWriter();
writer.setFields(fields);
for(int i=0;i<fieldCount;i++)
{
writer.addRecord(data[i]);
}
writer.write(fos);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{
fos.close();
}catch(Exception e){}
}

}

可以看到定义JavaDBF表结构或者添加数据时是通过传递数组实现,也就是说只要我们有了这些用来构造表结果和表示结果集的数组就有了DBF文件,那么我们可以通过类似下面这样的函数把ResultSet信息转换成数组信息。

Java代码


ResultSet得相关参数代码片断,下面的代码对类型判断和转换还不全面,如果还有其他字段请自行添加

Java代码


try {
ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount();
strutName = new String[columnCount];
strutType = new byte[columnCount];
rs.last();
int itemCount = rs.getRow();
rs.first();
data = new Object[itemCount][columnCount];
for (int i = 1; i <= columnCount; i++){
int type = (byte) meta.getColumnType(i);
//2是BigDecimal
if(type == 2){
strutType[i-1] = DBFField.FIELD_TYPE_N;
}
//12是String
else if(type == 12){
strutType[i-1] = DBFField.FIELD_TYPE_C;
}
//91是java.util.Date
else if(type == 91){
strutType[i-1] = DBFField.FIELD_TYPE_D;
}
strutName[i-1] = meta.getColumnName(i);
}
for (int i = 0; rs.next(); i++){
for (int j = 0; j < columnCount; j++){
Object da = rs.getObject(j+1);
if(da instanceof BigDecimal){
Double d = Double.parseDouble(da.toString());
data[i][j] = d;
}else{
data[i][j] = da;
}
}
}
}catch (Exception e){
e.printStackTrace();
}finally{
rs = null;
}

上面采用的是传统方法进行导出dbf文件,如果大数据量导出时,就要先将文件生成到服务器端,然后从response里拿输入流,将刚生成的文件写到客户端,也就是多一个文件流写入的过程。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: