DBF文件格式是一種比較“古老”的數據庫文件格式了。要不是最近項目中需要,筆者恐怕到今天也不曾聽說過DBF文件格式。
作用:DBF數據庫格式是DOS系統中的dBase數據庫和FoxPro數據庫所使用的數據庫格式。如今,如果電腦上沒有安裝這兩款軟件,可以使用Excel打開。
package zj.jdbc.util;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.linuxense.javadbf.DBFDataType;
import com.linuxense.javadbf.DBFField;
import com.linuxense.javadbf.DBFReader;
import com.linuxense.javadbf.DBFWriter;
import zj.check.util.CheckUtil;
import zj.common.exception.ServiceException;
import zj.io.util.FileUtil;
import zj.java.util.JavaUtil;
import zj.jdbc.bean.DBFRead;
import zj.jdbc.bean.DBFWrite;
import zj.reflect.util.TypeUtil;
/**
* 類名 :DBFUtil<br>
*
* @version 1.00 (2014.09.15)
* @author SHNKCS 張軍 {@link <a target=_blank href="http://www.dlhighland.cn">上海加盾信息科技有限公司</a> <a target=_blank href="http://www.dlhighland.cn">張軍個人網站</a> <a target=_blank href="http://user.qzone.qq.com/360901061/">張軍QQ空間</a>}
*/
public class DBFUtil implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(DBFUtil.class);
// str = Md5Util.toMd5("zhangjundbf201611040930");
// System.out.println(str);
// str = Md5Util.toMd5("zhangjundbf201611040931");
// System.out.println(str);
/**
* 讀取DBF數據
*
* @param path
* dbf文件路徑
* @author 張軍
* @date 2015-11-03 21:59:00
* @modifiyNote
* @version 1.0
* @return
*/
public static void readDBF(DBFRead p_read) {
// 清空值
p_read.reset();
InputStream fis = null;
try {
// 讀取文件的輸入流
fis = new FileInputStream(p_read.paramPath);
// 根據輸入流初始化一個DBFReader實例,用來讀取DBF文件信息
p_read.rtnReader = new DBFReader(fis, p_read.paramCharset);
// 調用DBFReader對實例方法得到path文件行數,包含刪除和隱藏的行
p_read.rtnRecordsCount = p_read.rtnReader.getRecordCount();
// 調用DBFReader對實例方法得到path文件中字段的個數
p_read.rtnFieldsCount = p_read.rtnReader.getFieldCount();
// 取出字段信息
for (int i = 0; i < p_read.rtnFieldsCount; i++) {
// 獲取DBF字段信息
DBFField field = p_read.rtnReader.getField(i);
p_read.rtnFields.add(field);
// 轉換為大寫
String fieldName = JavaUtil.toUpperCase(JavaUtil.trim(field.getName()));
p_read.rtnFieldNames.add(fieldName);
}
Object[] rowValue = null;
// 一條條取出path文件中記錄
while ((rowValue = p_read.rtnReader.nextRecord()) != null) {
// 取出字段信息
p_read.rtnCheckColFieldValue.clear();
for (int i = 0; i < p_read.rtnFieldsCount; i++) {
// 獲取DBF字段信息
DBFField field = p_read.rtnReader.getField(i);
String fieldName = JavaUtil.toUpperCase(JavaUtil.trim(field.getName()));
Object fieldValue = rowValue[i];
p_read.rtnCheckColFieldValue.put(fieldName, fieldValue);
}
// 用此rtnCheckColFieldValue鍵值進行判斷
int checkRow = p_read.checkRow();
if (p_read.BREAK == checkRow) {
break;
}
if (p_read.CONTINUE == checkRow) {
continue;
}
if (p_read.OK != checkRow) {
throw new ServiceException("返回值只支持[OK、CONTINUE、BREAK]");
}
// 實例化一行行值
Map<String, Object> rowValues = new HashMap<String, Object>();
// 添加一行記錄值
p_read.rtnRowFieldValues.add(rowValues);
p_read.rtnRowValues.add(rowValue);
// 取出字段信息
for (int i = 0; i < p_read.rtnFieldsCount; i++) {
// 獲取DBF字段信息
DBFField field = p_read.rtnReader.getField(i);
String fieldName = JavaUtil.toUpperCase(JavaUtil.trim(field.getName()));
Object fieldValue = rowValue[i];
// // 轉換值Double->String
// if (fieldValue instanceof Double) {
// java.text.DecimalFormat df = new java.text.DecimalFormat();
// df.setGroupingUsed(false);
// fieldValue = df.format(fieldValue);
// }
// 添加一行行值
rowValues.put(fieldName, fieldValue);
// 添加對應的鍵值數據
List<Object> values = p_read.rtnColFieldValues.get(fieldName);
if (values == null) {
values = new ArrayList<Object>();
p_read.rtnColFieldValues.put(fieldName, values);
}
// 添加值
values.add(fieldValue);
// System.out.print(fieldName + ":" + fieldValue + "\t");
}
// System.out.println();
}
} catch (Exception e) {
throw new ServiceException(e);
} finally {
try {
fis.close();
} catch (Exception e) {
}
}
}
/**
* 通用寫dbf文件
*
* @param p_path
* DBF文件路徑
* @param p_fields
* 字段值,下面4個字段必須填寫
* @see {@link com.linuxense.javadbf.DBFField#setFieldLength(int)};
* @see {@link com.linuxense.javadbf.DBFField#setDecimalCount(int)}};
* @see {@link com.linuxense.javadbf.DBFField#setName(String)};
* @see {@link com.linuxense.javadbf.DBFField#setDataType(byte)};
* @see byte:{@link com.linuxense.javadbf.DBFDataType#類型}(byte code, int minSize, int maxSize, int defaultSize, boolean writeSupported)
* @see byte:{@link com.linuxense.javadbf.DBFDataType#CHARACTER}('C', 1, 254, 0, true)
* @see byte:{@link com.linuxense.javadbf.DBFDataType#DATE}('D', 8, 8, 8, true)
* @see byte:{@link com.linuxense.javadbf.DBFDataType#FLOATING_POINT}('F', 1, 20, 0, true)
* @see byte:{@link com.linuxense.javadbf.DBFDataType#LOGICAL}('L', 1, 1, 1, true)
* @see byte:{@link com.linuxense.javadbf.DBFDataType#NUMERIC}('N', 1, 32, 0, true)
*
* @param p_rowValues
* 行值
*/
public static void writeDBF(DBFWrite p_write) {
OutputStream fos = null;
try {
if (CheckUtil.isNull(p_write.paramPath)) {
throw new ServiceException("paramPath:文件路徑不能為空");
}
// 創建文件對應的上級目錄
File v_pfile = new File(FileUtil.getParentPath(p_write.paramPath));
if (!v_pfile.exists()) {
v_pfile.mkdirs();
}
if (p_write.paramRead != null) {
// 自動賦值
p_write.paramFields = p_write.paramRead.rtnFields;
p_write.paramRowValues = p_write.paramRead.rtnRowValues;
}
// 定義DBF文件字段
int v_columnSize = p_write.paramFields.size();
// 轉換為list好操作
List<DBFField> v_fieldList = new ArrayList<DBFField>();
// 添加列
for (int i = 0; i < v_columnSize; i++) {
try {
DBFField r_field = p_write.callbackResetField(p_write.paramFields.get(i));
if (r_field == null) {
continue;
}
v_fieldList.add(r_field);
} catch (Exception e) {
// 異常退出
logger.error("設置字段異常,中斷循環", e);
break;
}
}
// 最終的字段
v_fieldList = p_write.callbackResetFields(v_fieldList);
DBFField[] v_fields = JavaUtil.listToArray(v_fieldList, DBFField.class);
// 定義DBFWriter實例用來寫DBF文件
// 定義輸出流,并關聯的一個文件
fos = new BufferedOutputStream(new FileOutputStream(p_write.paramPath));
DBFWriter writer = new DBFWriter(fos, p_write.paramCharset);
// 把字段信息寫入DBFWriter實例,即定義表結構
writer.setFields(v_fields);
for (Object[] v_rowValue : p_write.paramRowValues) {
try {
List<Object> p_rowValue = Arrays.asList(v_rowValue);
// 不執行下面方法,則報:java.lang.UnsupportedOperationException
p_rowValue = new ArrayList<Object>(p_rowValue);
// System.out.println("old:" + p_rowValue.size());
// 如果不想改變p_rowValue值,則使用JavaUtil.deepCopy(p_rowValue)深度拷貝list
List<Object> r_rowValue = p_write.callbackResetRowValue(v_fieldList, p_rowValue);
if (r_rowValue == null) {
continue;
}
// System.out.println("new:" + p_rowValue.size());
writer.addRecord(JavaUtil.listToArray(r_rowValue, Object.class));
} catch (Exception e) {
// 異常退出
logger.error("設置值異常,中斷循環", e);
break;
}
}
// 寫入數據
writer.close();
} catch (Exception e) {
throw new ServiceException(e);
} finally {
try {
fos.close();
} catch (Exception e) {
}
}
}
/**
* 導出DBF文件
*
* @param p_titles
* 標題,格式為,名稱|類型|長度|精度
* @param p_listValues
* 值
* @param dbfFile
* DBF文件
*/
public static void exportDBF(List<String> p_titles, List<Object[]> p_listValues, File dbfFile) {
exportDBF(null, p_titles, p_listValues, dbfFile);
}
/**
* 導出DBF文件
*
* @param write
* DBF寫入對象
* @param p_titles
* 標題,格式為,名稱|類型|長度|精度
* @param p_listValues
* 值
* @param dbfFile
* DBF文件
*/
public static void exportDBF(DBFWrite write, List<String> p_titles, List<Object[]> p_listValues, File dbfFile) {
if (write == null)
write = new DBFWrite();
for (String v_title : p_titles) {
String[] v_titleAry = JavaUtil.split(v_title, "|");
String name = "";
// 默認字符
char type = 'C';
// 默認長度為100
int length = 0;
int decimalCount = 0;
if (v_titleAry.length == 1) {
// 默認字符
name = v_titleAry[0];
} else if (v_titleAry.length == 2) {
name = v_titleAry[0];
type = JavaUtil.toUpperCase(v_titleAry[1]).toCharArray()[0];
} else if (v_titleAry.length == 3) {
name = v_titleAry[0];
type = JavaUtil.toUpperCase(v_titleAry[1]).toCharArray()[0];
length = TypeUtil.Primitive.intValue(v_titleAry[2]);
} else if (v_titleAry.length == 4) {
name = v_titleAry[0];
type = JavaUtil.toUpperCase(v_titleAry[1]).toCharArray()[0];
length = TypeUtil.Primitive.intValue(v_titleAry[2]);
decimalCount = TypeUtil.Primitive.intValue(v_titleAry[3]);
}
// System.out.println(name + "," + type + "," + length + "," + decimalCount);
if (length == 0) {
// 一般由自己根據情況定義
length = write.defaultSize;
}
write.paramFields.add(new DBFField(name, DBFDataType.fromCode(type), length, decimalCount));
}
// List<Map<String, Object>> v_listMap = queryResult.rtnDatas;
// System.out.println(v_listMap);
// for (Map<String, Object> v_map : v_listMap) {
// System.out.println(v_map);
// }
// System.out.println(p_listValues);
// for (Object[] v_listValue : p_listValues) {
// System.out.println(Arrays.toString(v_listValue));
// }
write.paramRowValues = p_listValues;
write.paramPath = dbfFile;
writeDBF(write);
}
}
本文為張軍原創文章,轉載無需和我聯系,但請注明來自張軍的軍軍小站,個人博客http://www.dlhighland.cn
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

