用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>- 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(
- String dbfName,
- String[] strutName,
- byte[] strutType,
- int[] strutLength,
- Object[][] data
- )
- {
- OutputStream fos = null;
- try
- {
- 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]);
- fields[i].setFieldLength(strutLength[i]);
- }
- DBFWriter writer = new DBFWriter();
- writer.setFields(fields);
- for(int i=0;i<fieldCount;i++)
- {
- writer.addRecord(data[i]);
- }
- fos = new FileOutputStream(dbfName);
- writer.write(fos);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- finally
- {
- try{
- fos.close();
- }catch(Exception e){}
- }
- }
可以看到定義JavaDBF表結構或者添加數據時是通過傳遞數組實現,也就是說只要我們有了這些用來構造表結果和表示結果集的數組就有了DBF文件,那麼我們可以通過類似下面這樣的函數把ResultSet信息轉換成數組信息。
- public static void ResultsetToArray(ResultSet rs)
- {
- try
- {
- ResultSetMetaData meta = rs.getMetaData();
- int columnCount = meta.getColumnCount();
- String[] strutName = new String[columnCount];
- byte[] strutType = new byte[columnCount];
- rs.last();
- int itemCount = rs.getRow();
- rs.first();
- Object[][] data = new Object[columnCount][itemCount];
- for(int i=0;i<columnCount;i++)
- {
- strutType[i] = (byte)meta.getColumnType(i);
- strutName[i] = meta.getColumnName(i);
- }
- for(int i=0;rs.next();i++)
- {
- for(int j=0;j<columnCount;j++)
- {
- data[i][j] = rs.getObject(j);
- }
- }
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
細心的讀者可能會發現:strutType[i] = (byte)meta.getColumnType(i)這條語句是不可靠的,的卻,這裏的代碼我省略了,JavaDBF中的字段類型表示和ResultSetMetaData中的字段類型表示應該是不一致的,這裏做一個類型映射和轉換即可。
</o:p>