整理完成 DBF 檔案讀寫的 Java 原始碼,供開發者參考使用。本文重點解析關鍵邏輯:標頭解析、欄位定義讀取與記錄資料提取。
private void init(InputStream inputstream) throws JDBFException {
try {
stream = new DataInputStream(inputstream);
int fieldCount = readHeader(); // 讀取標頭,取得欄位數
fields = new JDBField[fieldCount];
int recordLength = 1; // 記錄長度起始值(含刪除標記位元組)
for (int k = 0; k < fieldCount; k++) {
fields[k] = readFieldHeader(); // 讀取每個欄位定義
recordLength += fields[k].getLength(); // 累加欄位長度
}
if (stream.read() < 1) throw new JDBFException("Unexpected end of file reached.");
nextRecord = new byte[recordLength];
try {
stream.read(new byte[263]); // 略過標頭結尾保留區塊
stream.readFully(nextRecord); // 讀取第一筆記錄
} catch (EOFException eofexception) {
nextRecord = null;
stream.close();
}
} catch (IOException ioexception) {
throw new JDBFException(ioexception);
}
}
private int readHeader() throws IOException, JDBFException {
byte[] headerBytes = new byte[16];
try {
stream.readFully(headerBytes);
} catch (EOFException e) {
throw new JDBFException("Unexpected end of file reached.");
}
// 位元組 8、9 記錄標頭長度(含終止標記)
int headerLen = headerBytes[8] & 0xFF;
headerLen += 256 * (headerBytes[9] & 0xFF);
headerLen -= 264; // 扣除固定標頭大小
headerLen = --headerLen / 32; // 每欄位 32 位元組,換算欄位數
// 讀取標頭結尾標記
try {
stream.readFully(headerBytes);
} catch (EOFException e) {
throw new JDBFException("Unexpected end of file reached.");
}
return headerLen;
}
詳細格式定義請參考:DBF File Format Specification
RandomAccessFile 或 NIO 提升效能。