最近的一个项目需要动态生成DBF文件,用到JavaDBF,简单介绍一下
最新版本:0.4.0,最后发布时间还是在2004年4月1日,看来DBF真是老了。老归老,有些时候还是得用。
下面是分别是读取和写DBF文件以及其他操作函数(关键信息的解释我放在了注释里,这样看起来会更方便):
读取DBF文件:
- package dbf;
- import java.io.FileInputStream;
- import java.io.InputStream;
- import com.linuxense.javadbf.DBFField;
- import com.linuxense.javadbf.DBFReader;
- public class readDBF {
- 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) {
- }
- }
- }
- public static void main(String[] args) {
- readDBF.readDBF("c:/到货明细表.DBF");
- }
- }
写DBF文件:
- package dbf;
- import java.io.FileOutputStream;
- import java.io.OutputStream;
- import com.linuxense.javadbf.DBFField;
- import com.linuxense.javadbf.DBFWriter;
- public class writeDBF {
- 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文件,不用每次都去写重复的代码。
- package dbf;
- import java.io.FileOutputStream;
- import java.io.OutputStream;
- import com.linuxense.javadbf.DBFField;
- import com.linuxense.javadbf.DBFWriter;
- public class Snippet {
- 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) {
- }
- }
- }
- }
- 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中的字段类型表示应该是不一致的,这里做一个类型映射和转换即可。