1.应用MAVEN提供的javadbf.jar包
<dependency>
<groupId>com.linuxense</groupId>
<artifactId>javadbf</artifactId>
<version>0.4.0</version>
</dependency>
应用maven网站上下载的jar包会有写中文内容乱码的问题,因此自己又从网上下载了一个,下载地址
2.读DBF文件
/**
* @param path 文件路径
* @param encoding 文件编码
* @return responseInfo fields-文件标题列DBFField[] content-文件内容 List<String[]></String[]> status-0:成功 1:失败 msg-消息
* DBFField 数据类型 对应 数据库表中类型
* public static final byte FIELD_TYPE_C = 67; 字符型 char(length)
* public static final byte FIELD_TYPE_L = 76; 逻辑型 numeric(1,0)
* public static final byte FIELD_TYPE_N = 78; 数值型 numeric(length,decimalCount)
* public static final byte FIELD_TYPE_F = 70; 浮点型 float
* public static final byte FIELD_TYPE_D = 68; 日期型 datetime
* public static final byte FIELD_TYPE_M = 77; memo备注型 text
* */
public static ResponseInfo readDBF(String path, String encoding){
ResponseInfo responseInfo = new ResponseInfo();
InputStream fis= null;
try{
//读取文件的输入流
fis = new FileInputStream(path);
//根据输入流初始化一个DBFReader实例,用来读取DBF文件信息
DBFReader reader = new DBFReader(fis);
reader.setCharactersetName(encoding);
//存放文件内容
List<String[]> content = new ArrayList<String[]>();
//调用DBFReader对实例方法得到path文件中字段的个数
int fieldCount = reader.getFieldCount();
logger.info("fieldCount: " + fieldCount);
//获取字段类型名称信息
DBFField[] fields = new DBFField[fieldCount];
for(Integer i=0; i<fieldCount; i++){
DBFField field = reader.getField(i);
fields[i] = field;
logger.info("The DBF file fields: ");
logger.info(field.getName() + " : type - " + field.getDataType() + " length - " + field.getFieldLength() + " decimal - " + field.getDecimalCount() );
}
//一条条取出dbf中的文件内容 将其转化为字符串存放
Integer rowCount = 0;
Object[] rowValues;
String[] rowStrArr;
while((rowValues = reader.nextRecord()) != null){
rowStrArr = new String[rowValues.length];
String rowStr = "";
for(Integer i=0; i<rowValues.length; i++){
String tempValueStr = "";
if(rowValues[i] != null && !rowValues[i].equals("")) {
if (fields[i].getDataType() == 68) {//日期型特殊处理
tempValueStr = new SimpleDateFormat("yyyy/MM/dd").format(rowValues[i]);
}else{
tempValueStr = rowValues[i].toString().trim();
}
}
rowStrArr[i] = tempValueStr;
rowStr += rowStrArr[i] + "\t";
}
content.add(rowStrArr);
if(rowCount<10) {
logger.info(rowStr);
}
rowCount++;
}
logger.info("读取的DBF文件内容记录数: " + rowCount + "; content length: " + content.size());
responseInfo.setStatusWithBool(true);
responseInfo.setMsg("读取文件成功");
responseInfo.put("content",content);
responseInfo.put("fields",fields);
fis.close();
}catch(Exception e){
logger.error("读取DBF文件 -- " + path +"时,出现异常: " + e.getMessage());
responseInfo.setStatusWithBool(false);
responseInfo.setMsg("读取DBF文件 -- " + path +"时,出现异常: " + e.getMessage());
}
return responseInfo;
}
3.写DBF文件
/**
* @param path 文件路径
* @param encoding 文件编码
* @return responseInfo fields-文件标题列DBFField[] content-文件内容 List<String[]></String[]> status-0:成功 1:失败 msg-消息
* DBFField 数据类型 对应 数据库表中类型
* public static final byte FIELD_TYPE_C = 67; 字符型 char(length)
* public static final byte FIELD_TYPE_L = 76; 逻辑型 numeric(1,0)
* public static final byte FIELD_TYPE_N = 78; 数值型 numeric(length,decimalCount)
* public static final byte FIELD_TYPE_F = 70; 浮点型 float
* public static final byte FIELD_TYPE_D = 68; 日期型 datetime
* public static final byte FIELD_TYPE_M = 77; memo备注型 text 不可写入MEMO类型的 javadbf不处理MEMO类型的
* */
public static ResponseInfo writeDBF(String path, List<String[]> content,DBFField[] fields,String encoding){
OutputStream fos = null;
ResponseInfo responseInfo = new ResponseInfo();
if(content == null || fields == null){
responseInfo.setStatusWithBool(false);
responseInfo.setMsg("写DBF文件失败,参数为空");
return responseInfo;
}
logger.info("write dbf content: " + JSON.toJSONString(content) + "; fields: " + JSON.toJSONString(fields));
try{
fos = new FileOutputStream(path);
//追加文件
//fos = new FileOutputStream(path,true);
DBFWriter writer = new DBFWriter();
writer.setCharactersetName(encoding);
//文件标题
writer.setFields(fields);
//写入文件内容
Integer fieldCount = fields.length;
for(Integer i=0; i<content.size(); i++){
String[] temp = content.get(i);
if(temp.length != fieldCount){
String msg = "DBF文件写入失败!";
logger.info(msg + "第" + i + "行文件内容的字段数和文件标题的字段数不一致!");
responseInfo.setStatusWithBool(false);
responseInfo.setMsg(msg + "文件内容的字段数和文件标题的字段数不一致!");
return responseInfo;
}
//按类型将数据放入行数组内
Object[] rowValues = new Object[fieldCount];
for(Integer j=0; j<fieldCount; j++){
byte type = fields[j].getDataType();
switch(type){
case 67://字符型
rowValues[j] = temp[j];
break;
case 76://逻辑型
//rowValues[j] = (ClassUtil.isValidParam(temp[j])? new Boolean(temp[j]) : null);
if(ClassUtil.isValidParam(temp[j])){
Boolean tempValue = new Boolean(temp[j]);
logger.info(tempValue + "; tempValue == true: " + (tempValue == true));
if(tempValue == true){
rowValues[j] = Boolean.TRUE;
}else{
rowValues[j] = Boolean.FALSE;
}
}else{
rowValues[j] = null;
}
//logger.info(rowValues[j]);
break;
case 78://数值型
rowValues[j] = (ClassUtil.isValidParam(temp[j])? new Double(temp[j]) : null);
break;
case 70://浮点型
rowValues[j] = (ClassUtil.isValidParam(temp[j])? new Double(temp[j]) : null);
break;
case 68://datetime 需要测试
if(ClassUtil.isValidParam(temp[j])) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Date dateValue = sdf.parse(temp[j]);
rowValues[j] = dateValue;
}else{
rowValues[j] = null;
}
break;
case 77://text
rowValues[j] = temp[j];
break;
default:
rowValues[j] = temp[j];
break;
}//switch
}//for
writer.addRecord(rowValues);
//logger.info("rowValues length: " + rowValues.length + "; " + JSON.toJSONString(rowValues));
}
//写入数据
writer.write(fos);
responseInfo.setStatusWithBool(true);
responseInfo.setMsg("DBF文件 -- "+ path + " 写入成功!");
logger.info("DBF文件 -- "+ path + " 写入成功!写入记录行数为: " + content.size() );
//fos.close();
}catch(Exception e){
String msg = "DBF文件 -- " + path + " 写入时,出现异常:" + e.getMessage();
responseInfo.setStatusWithBool(false);
responseInfo.setMsg(msg);
logger.error(msg );
} finally {
try {
fos.close();
} catch (Exception e) {
}
}
return responseInfo;
}
4.测试读写文件
//测试写DBF文件
@Test
public void writeDBF(){
String filePath = "D:\\测试数据\\自己创建DBF\\ 2_1.dbf";
List<String[]> content = new ArrayList<String[]>();
Integer fieldCount = 9;
DBFField[] fields = new DBFField[fieldCount];
String encoding = "GBK";
for(Integer i=0; i<fieldCount; i++){
fields[i] = new DBFField();
}
try {
//0-char
fields[0].setName("COL_CHAR");
fields[0].setDataType(DBFField.FIELD_TYPE_C);
fields[0].setFieldLength(15);
//1-numeric(15,6)
fields[1].setName("COL_NUMER1");
fields[1].setDataType(DBFField.FIELD_TYPE_N);
fields[1].setFieldLength(15);
fields[1].setDecimalCount(6);
//2-numeric(15)
fields[2].setName("COL_NUMER2");
fields[2].setDataType(DBFField.FIELD_TYPE_N);
fields[2].setFieldLength(15);
//3-datetime
fields[3].setName("COL_DATE");
fields[3].setDataType(DBFField.FIELD_TYPE_D);
//4-float
fields[4].setName("COL_FLOAT");
fields[4].setDataType(DBFField.FIELD_TYPE_F);
fields[4].setFieldLength(15);
//5-L
fields[5].setName("COL_LOGIC");
fields[5].setDataType(DBFField.FIELD_TYPE_L);
fields[5].setFieldLength(1);
//6-M
fields[6].setName("COL_MEMO1");
fields[6].setDataType(DBFField.FIELD_TYPE_C);
fields[6].setFieldLength(16);
//7-M
fields[7].setName("COL_MEMO2");
fields[7].setDataType(DBFField.FIELD_TYPE_C);
fields[7].setFieldLength(16);
//8-M
fields[8].setName("备注");
fields[8].setDataType(DBFField.FIELD_TYPE_C);
fields[8].setFieldLength(100);
}catch(Exception e){
logger.info("写DBF文件时,设置字段出现异常:" + e.getMessage());
}
String[] str1 = new String[fieldCount];
str1[0] = "";
str1[1] = null;
str1[2] = "33.5";
str1[3] = "2016/12/3";
str1[4] = "23";
str1[5] = "1";
str1[6] = "6666";
str1[7] = "gggg6666";
str1[8] = "ggg";
//mumeric长度超过规定长度
String[] str2 = new String[fieldCount];
str2[0] = "fffgg212222222222222222222244";//长度过15
str2[1] = "223.566";
str2[2] = "33.555";//没有规定小数点长度
str2[3] = null;
str2[4] = "23.68"; //float
str2[5] = "1";
str2[6] = "6666dddddd";
str2[7] = "gggg6666hhhhhhhhhhhhhhhh";
str2[8] = "第一列字符串长度超过十五;第5列float类型小数点位数超过6";
String[] str3 = new String[fieldCount];
str3[0] = "fffgg11111";
str3[1] = "223.5666666666666666";//小数点超过六
str3[2] = "33";
str3[3] = "";
str3[4] = "23.6";
str3[5] = "12";
str3[6] = "6666";
str3[7] = "gggg6666";
str3[8] = "第二列NUMERIC小数点位数超过六;第六列logic类型是12";
String[] str4 = new String[fieldCount];
str4[0] = "fffgg";
str4[1] = "223.5";
str4[2] = "33";
str4[3] = "2016/11/3";
str4[4] = "23.6";
str4[5] = "";
str4[6] = "6666dddddddddddd111111111115555555";//长度超过十六
str4[7] = "gggg6666";
str4[8] = "第七列MEMO长度超过十六";
String[] str5 = new String[fieldCount];
str5[0] = "fffgg";
str5[1] = "223.5";
str5[2] = "33";
str5[3] = "2016/11/3 22:30:45";
str5[4] = "23.6";
str5[5] = "true";
str5[6] = "6666dddd";
str5[7] = "gggg6666";
str5[8]= "true 第四列日期类型加时间";
String[] str6 = new String[fieldCount];
str6[0] = "fffgg";
str6[1] = "223.5";
str6[2] = "33";
str6[3] = "2016/11/3 22:30";
str6[4] = "23.6";
str6[5] = null;
str6[6] = "6666dddd";
str6[7] = "gggg6666";
str6[8]= "false 第四列日期类型不合法";
content.add(str1);
content.add(str2);
content.add(str3);
content.add(str4);
content.add(str5);
content.add(str6);
ResponseInfo responseInfo = FileHelper.writeDBF(filePath,content,fields,encoding);
logger.info("写入结果:");
logger.info(JSON.toJSONString(responseInfo));
ResponseInfo responseInfo2 = FileHelper.readDBF(filePath, "GBK");
logger.info("读取结果:");
logger.info(JSON.toJSONString(responseInfo2));
}
5.注意要点
(1)日期型
a. java.util.Date转String:
String tempValueStr = new SimpleDateFormat("yyyy/MM/dd").format(rowValues[i]);
b. String “Mon Dec 31 00:00:00 CST 2012”形式的转java.util.Date:
public class DateHelper {
//字符串转化为Date
//用法举例:String str = "Mon Dec 31 00:00:00 CST 2012";
// java.util.Date tempDate = DateHelper.parse(str, "EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
public static Date parse(String str, String pattern, Locale locale) {
if(str == null || pattern == null) {
return null;
}
try {
return new SimpleDateFormat(pattern, locale).parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
//Date转化为字符串
public static String format(Date date, String pattern, Locale locale) {
if(date == null || pattern == null) {
return null;
}
return new SimpleDateFormat(pattern, locale).format(date);
}
}
c. String “yyyy/MM/dd” 转 java.util.Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Date dateValue = sdf.parse(str);
d.dbf文件中的日期格式为yyyy/MM/dd
读文件时将日期存储为”yyyy/MM/dd”形式的字符串,
写文件时在将字符串转化为”yyyy/MM/dd”类型的日期
(2)Boolean型
String str1 = "false";
Boolean bb = new Boolean(str1);
Integer temp = (bb==false ? 1:0);
logger.info("bb: " + bb + " ; temp: " + temp);
Boolean bb1 = new Boolean("1");
logger.info("bb1: " + bb1 + "; bb1.equals(Boolean.TRUE): " + bb1.equals(Boolean.TRUE));
Boolean bb2 = new Boolean("true");//true
logger.info("bb2: " + bb2 + "; Boolean.true == bb2: " + (bb2 == Boolean.TRUE) + "; bb2 == true: " + (bb2 == true));
Boolean bb3 = new Boolean(true); //true
logger.info("bb3: " + bb3 + "; Boolean.TRUE: " + Boolean.TRUE + "; bb3.equals(Boolean.TRUE: " + (bb3.equals(Boolean.TRUE)));
Boolean bb4 = Boolean.TRUE;
logger.info("bb4: " + bb4 + "; Boolean.true == bb4: " + (bb4 == Boolean.TRUE));
输出为:
bb: false ; temp: 1
bb1: false; bb1.equals(Boolean.TRUE): false
bb2: true; Boolean.true == bb2: false; bb2 == true: true
bb3: true; Boolean.TRUE: true; bb3.equals(Boolean.TRUE: true
bb4: true; Boolean.true == bb4: true
注意:
- Boolean a = new Boolean(true); 则a == Boolean.TRUE 为false,a.equals(Boolean.TRUE)为true。 ==比较的是地址是不是一样, equals是比较的内容
- 在用javadbf写DBF文件时,若有单元内容为逻辑型,要用Boolean.TRUE或Boolean.FALSE赋值,否则会出错,除Boolean.TRUE之外的所有值都会按false处理
if(tempValue == true){
rowValues[j] = Boolean.TRUE;
}else{
rowValues[j] = Boolean.FALSE;
}
(3)Float类型
用javadbf写DBF文件时,Float类型用new Double()来封装,否则会出错