论坛首页 Java企业应用论坛

用JavaDBF操作(读、写)DBF文件

浏览 18409 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-07-27  

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">200441</st1:chsdate>,看来DBF真是老了。老归老,有些时候还是得用。<o:p></o:p>

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

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

<o:p>
java 代码
  1. public static void readDBF(String path)   
  2.   
  3.     {   
  4.   
  5.        InputStream fis = null;   
  6.   
  7.         try    
  8.   
  9.         {   
  10.   
  11.             //读取文件的输入流   
  12.   
  13.             fis  = new FileInputStream(path);   
  14.   
  15.             //根据输入流初始化一个DBFReader实例,用来读取DBF文件信息   
  16.   
  17.             DBFReader reader = new DBFReader(fis);    
  18.   
  19.             //调用DBFReader对实例方法得到path文件中字段的个数   
  20.   
  21.             int fieldsCount = reader.getFieldCount();   
  22.   
  23.             //取出字段信息   
  24.   
  25.             forint i=0; i<fieldsCount; i++)    
  26.   
  27.             {   
  28.   
  29.               DBFField field = reader.getField(i);   
  30.   
  31.               System.out.println(field.getName());   
  32.   
  33.             }   
  34.   
  35.             Object[] rowValues;   
  36.   
  37.             //一条条取出path文件中记录   
  38.   
  39.             while((rowValues = reader.nextRecord()) != null)    
  40.   
  41.             {   
  42.   
  43.               forint i=0; i<rowValues.length; i++)    
  44.   
  45.               {   
  46.   
  47.                 System.out.println(rowValues[i]);   
  48.   
  49.               }   
  50.   
  51.             }   
  52.   
  53.           }   
  54.   
  55.           catch(Exception e)    
  56.   
  57.           {   
  58.   
  59.           e.printStackTrace();   
  60.   
  61.           }   
  62.   
  63.           finally  
  64.   
  65.           {   
  66.   
  67.           try{   
  68.   
  69.                fis.close();   
  70.   
  71.           }catch(Exception e){}   
  72.   
  73.           }   
  74.   
  75.     }   

 

DBF文件:

java 代码

  1. public static void writeDBF(String path)   
  2.   
  3.   
  4.   
  5.  OutputStream fos = null;   
  6.   
  7.  try  
  8.   
  9.  {   
  10.   
  11.      //定义DBF文件字段   
  12.   
  13.      DBFField[] fields = new DBFField[3];   
  14.   
  15.      //分别定义各个字段信息,setFieldName和setName作用相同,   
  16.   
  17.      //只是setFieldName已经不建议使用   
  18.   
  19.      fields[0] = new DBFField();   
  20.   
  21.      //fields[0].setFieldName("emp_code");   
  22.   
  23.      fields[0].setName("semp_code");   
  24.   
  25.      fields[0].setDataType(DBFField.FIELD_TYPE_C);   
  26.   
  27.      fields[0].setFieldLength(10);   
  28.   
  29.   
  30.   
  31.      fields[1] = new DBFField();   
  32.   
  33.      //fields[1].setFieldName("emp_name");   
  34.   
  35.      fields[1].setName("emp_name");   
  36.   
  37.      fields[1].setDataType(DBFField.FIELD_TYPE_C);   
  38.   
  39.      fields[1].setFieldLength(20);   
  40.   
  41.   
  42.   
  43.      fields[2] = new DBFField();   
  44.   
  45.      //fields[2].setFieldName("salary");   
  46.   
  47.      fields[2].setName("salary");   
  48.   
  49.      fields[2].setDataType(DBFField.FIELD_TYPE_N);   
  50.   
  51.      fields[2].setFieldLength(12);   
  52.   
  53.      fields[2].setDecimalCount(2);   
  54.   
  55.   
  56.   
  57.      //DBFWriter writer = new DBFWriter(new File(path));   
  58.   
  59.      //定义DBFWriter实例用来写DBF文件   
  60.   
  61.      DBFWriter writer = new DBFWriter();   
  62.   
  63.      //把字段信息写入DBFWriter实例,即定义表结构   
  64.   
  65.      writer.setFields(fields);   
  66.   
  67.      //一条条的写入记录   
  68.   
  69.      Object[] rowData = new Object[3];   
  70.   
  71.      rowData[0] = "1000";   
  72.   
  73.      rowData[1] = "John";   
  74.   
  75.      rowData[2] = new Double(5000.00);   
  76.   
  77.      writer.addRecord(rowData);   
  78.   
  79.      rowData = new Object[3];   
  80.   
  81.      rowData[0] = "1001";   
  82.   
  83.      rowData[1] = "Lalit";   
  84.   
  85.      rowData[2] = new Double(3400.00);   
  86.   
  87.      writer.addRecord(rowData);   
  88.   
  89.      rowData = new Object[3];   
  90.   
  91.      rowData[0] = "1002";   
  92.   
  93.      rowData[1] = "Rohit";   
  94.   
  95.      rowData[2] = new Double(7350.00);   
  96.   
  97.      writer.addRecord(rowData);   
  98.   
  99.      //定义输出流,并关联的一个文件   
  100.   
  101.      fos = new FileOutputStream(path);   
  102.   
  103.      //写入数据   
  104.   
  105.      writer.write(fos);   
  106.   
  107.      //writer.write();   
  108.   
  109.  }catch(Exception e)   
  110.   
  111.  {   
  112.   
  113.      e.printStackTrace();   
  114.   
  115.  }   
  116.   
  117.  finally  
  118.   
  119.  {   
  120.   
  121.      try{   
  122.   
  123.      fos.close();   
  124.   
  125.      }catch(Exception e){}   
  126.   
  127.  }   

注意: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 代码
  1. public static void generateDbfFromArray(   
  2.   
  3.                                    String dbfName,   
  4.   
  5.                                    String[] strutName,   
  6.   
  7.                                    byte[] strutType,   
  8.   
  9.                                    int[] strutLength,   
  10.   
  11.                                    Object[][] data   
  12.   
  13.                                   )   
  14.   
  15. {   
  16.   
  17.    OutputStream fos = null;   
  18.   
  19.    try  
  20.   
  21.    {   
  22.   
  23.        int fieldCount = strutName.length;   
  24.   
  25.        DBFField[] fields = new DBFField[fieldCount];   
  26.   
  27.        for(int i=0;i<fieldCount;i++)   
  28.   
  29.        {   
  30.   
  31.           fields[i] = new DBFField();   
  32.   
  33.           fields[i].setName(strutName[i]);   
  34.   
  35.           fields[i].setDataType(strutType[i]);   
  36.   
  37.           fields[i].setFieldLength(strutLength[i]);   
  38.   
  39.        }   
  40.   
  41.        DBFWriter writer = new DBFWriter();   
  42.   
  43.        writer.setFields(fields);   
  44.   
  45.        for(int i=0;i<fieldCount;i++)   
  46.   
  47.        {   
  48.   
  49.        writer.addRecord(data[i]);   
  50.   
  51.        }   
  52.   
  53.        fos = new FileOutputStream(dbfName);   
  54.   
  55.        writer.write(fos);   
  56.   
  57.    }   
  58.   
  59.    catch(Exception e)   
  60.   
  61.    {   
  62.   
  63.        e.printStackTrace();   
  64.   
  65.    }   
  66.   
  67.    finally  
  68.   
  69.    {   
  70.   
  71.        try{   
  72.   
  73.        fos.close();   
  74.   
  75.        }catch(Exception e){}   
  76.   
  77.    }   
  78.   
  79. }  

 

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

java 代码
  1. public static void ResultsetToArray(ResultSet rs)   
  2.   
  3. {   
  4.   
  5.    try  
  6.   
  7.    {   
  8.   
  9.        ResultSetMetaData meta = rs.getMetaData();   
  10.   
  11.        int columnCount = meta.getColumnCount();   
  12.   
  13.        String[] strutName = new String[columnCount];   
  14.   
  15.        byte[] strutType = new byte[columnCount];   
  16.   
  17.        rs.last();   
  18.   
  19.        int itemCount = rs.getRow();   
  20.   
  21.        rs.first();   
  22.   
  23.        Object[][] data = new Object[columnCount][itemCount];   
  24.   
  25.        for(int i=0;i<columnCount;i++)   
  26.   
  27.        {   
  28.   
  29.           strutType[i] = (byte)meta.getColumnType(i);   
  30.   
  31.           strutName[i] = meta.getColumnName(i);   
  32.   
  33.        }   
  34.   
  35.   
  36.   
  37.        for(int i=0;rs.next();i++)   
  38.   
  39.        {      
  40.   
  41.           for(int j=0;j<columnCount;j++)   
  42.   
  43.           {   
  44.   
  45.               data[i][j] = rs.getObject(j);   
  46.   
  47.           }   
  48.   
  49.        }   
  50.   
  51.    }   
  52.   
  53.    catch(Exception e)   
  54.   
  55.    {   
  56.   
  57.        e.printStackTrace();   
  58.   
  59.    }   
  60.   
  61. }  

细心的读者可能会发现:strutType[i] = (byte)meta.getColumnType(i)这条语句是不可靠的,的却,这里的代码我省略了,JavaDBF中的字段类型表示和ResultSetMetaData中的字段类型表示应该是不一致的,这里做一个类型映射和转换即可。

 

 

 

</o:p>
   发表时间:2007-08-28  
我用了一样的方法读取dbf文件,但是读取的字段位置有问题。如“博客所有留言会成为论坛回贴”,本来属于一个字段的,但是用jdbfreader解析后就在两个字段里了。下载了个dbfviewer里看是正常的,dbf文件没有问题,请问你遇到过这种情况吗。
0 请登录后投票
   发表时间:2007-08-28  
kimfly 写道
我用了一样的方法读取dbf文件,但是读取的字段位置有问题。如“博客所有留言会成为论坛回贴”,本来属于一个字段的,但是用jdbfreader解析后就在两个字段里了。下载了个dbfviewer里看是正常的,dbf文件没有问题,请问你遇到过这种情况吗。

目前没有,你可以把你认为读取有问题的DBF文件传上来或者发给我,我可以帮你看看。
1 请登录后投票
   发表时间:2007-08-29  
谢谢了,后来我把他的源码发编译了调试了一下,好像在处理日期为空的时候有问题。暂时还没有处理,如有问题再请你帮忙。
1 请登录后投票
   发表时间:2007-10-17  
在java写DBF文件的时候,发现了字段中文写入为乱码,有解决的办法吗,
1 请登录后投票
   发表时间:2007-10-17  
楼上的为什么一篇文章就50分了?
1 请登录后投票
   发表时间:2007-10-18  
读取的时候乱码我倒是解决过,写的时候还没有发现过乱码
1 请登录后投票
   发表时间:2007-10-22  
DBFField里面的字段类型各自对应的数据库和SQL 字段类型 是什么样的对应关系啊
1 请登录后投票
   发表时间:2007-11-10  
读的时候发现乱码如何解决的?用什么编码? 解决了,dbfReader.setCharactersetName("GB2312");
1 请登录后投票
   发表时间:2007-11-10  
有谁操作过dbf中包含字段是日期时间型的吗,看了下源代码,没有处理这种类型的,有操作过的麻烦告诉下,谢谢。
1 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics