对于dbf文件读写有javadbf.jar支持,但是javadbf读写dbf文件使用的是输入输出流来操作的,如果dbf文件过大,效率将会非常低。而dbf-lib将避免了这个问题,关于dbf-lib的使用可访问https://github.com/DANS-KNAW/dans-dbf-lib。将工程打成jar包就可以调用了。
dbf-lib读写dbf文件是将dbf当作一个table来操作,他可以精确定位到读写和修改行,非常方便。原因是他使用的RandomAccessFile来操作的。
对于读写dbf,首先要创建一个Table对象。其次需要执行open()方法,否则调用其读写操作都会抛出异常。调用完后需要调用close()方法,不然资源将一直处于被占用状态。这和输入输出流的使用是一样的。
1.读dbf文件记录:
首先调用table构造方法创建Table对象(最好指定编码格式,因为如果dbf文件中存储的有中文很有可能乱码)。
open()方法有两个重载方法,无参默认为只读访问模式(这里指RandomAccessFile的权限)且文件不存在就报错。
getRecordsAt方法和getAllRecords方法都是获取记录,前者是从指定行数获取记录,后者是获取所有记录,即从0行开始获取记录。
然后调用close()关闭资源。关于Table中的方法可查看相关源码。
/**
* 获取记录
* @param dbfFile
* @param index开始位置
* @param count获取数据条数
* @param charsetName
* @return
* @throws CorruptedTableException
* @throws IOException
*/
public static List<Map<String, String>> getRecords(File dbfFile, int index, int count, String charsetName)
throws CorruptedTableException, IOException {
List<Map<String, String>> getRecordsList = new ArrayList();
// File dbfFile = new File(path);
Table table = new Table(dbfFile, charsetName);
table.open(IfNonExistent.ERROR);
Date nowLastModifiedDate = table.getLastModifiedDate();
List<Field> fields = table.getFields();
List<Record> records = table.getRecordsAt(index, count);
records.stream().forEach(record -> {
Map<String, String> recordMap = new HashMap();
fields.forEach(field -> {
recordMap.put(field.getName(), StringUtils.trimToNull(record.getStringValue(field.getName())));
});
getRecordsList.add(recordMap);
});
table.close();
return getRecordsList;
}
2.写记录到dbf文件
/**
* 添加数据
* @param path
* @param recordList记录
* @throws CorruptedTableException
* @throws IOException
*/
public static void addRecords(String path, List<Map<String, String>> recordList, String charsetName)
throws CorruptedTableException, IOException {
File dbfFile = new File(path);
Table table = new Table(dbfFile, charsetName);
table.open(IfNonExistent.ERROR);
recordList.stream().forEach(map -> {
Map<String, Value> rocordMap = new HashMap<>();
map.forEach((key, value) -> {
rocordMap.put(key, new StringValue(value, charsetName));
});
System.out.println(rocordMap);
try {
table.addRecord(new Record(rocordMap));
} catch (IOException | DbfLibException e) {
e.printStackTrace();
}
});
table.close();
}
3.创建dbf文件
创建dbf需要指定Field,而每一个Field要指定name,type和length
public static void creatDbf(String path, List<Map<String, String>> fieldMapList, String charsetName)
throws IOException, CorruptedTableException, InvalidFieldTypeException, InvalidFieldLengthException {
List<Field> fieldList = new ArrayList<>();
fieldMapList.stream().forEach(fieldMap -> {
fieldList.add(new Field(fieldMap.get("name"), Type.CHARACTER,
Integer.parseInt(fieldMap.get("length"))));
});
File dbfFile = new File(path);
Table table = new Table(dbfFile, Version.CLIPPER_5, fieldList, charsetName);
table.open(IfNonExistent.CREATE);
table.close();
}