1,用到的jar包:javadbf.jar。
2,如果是小数据量的导出,用普通的方法就可以。
用JavaDBF操作(读、写)DBF文件
最近的一个项目需要动态生成DBF文件,用到JavaDBF,简单介绍一下
官方网站:http://javadbf.sarovar.org/
官方英文指南:http://sarovar.org/docman/view.php/32/23/javadbf-tutorial.html
最新版本:<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真是老了。老归老,有些时候还是得用。
读取DBF文件:
<o:p>
- 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文件:
- 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文件,不用每次都去写重复的代码。
- 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信息转换成数组信息。
- 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;
- }