從 FoxPro (DBF) 遷移至 Oracle 時,需將大量 DBF 檔案轉換為 SQL*Loader 可用的**控制檔 (.ctl)、資料檔 (.dat/.txt)、建表 SQL (.sql)**。手工編寫極易在位置計算 (POSITION) 上出錯。本文提供完整 C++ 程式 load.cpp,自動解析 DBF 檔頭與欄位定義,一次產生三種檔案,大幅提升遷移效率。
| 區塊 | 位移 | 大小 | 說明 |
|---|---|---|---|
| 檔頭標識 | 0 | 1 Byte | 0x03 (無 Memo) / 0x83 (有 Memo) |
| 最後更新 | 1-3 | 3 Bytes | YYMMDD |
| 記錄筆數 | 4-7 | 4 Bytes | Little-endian DWORD |
| 檔頭長度 | 8-9 | 2 Bytes | 含欄位定義 + 結束標識 |
| 記錄長度 | 10-11 | 2 Bytes | 含刪除旗標 1 Byte |
| 欄位定義 | 32~N | 32 Bytes/欄 | 名稱(11)、類型(1)、位移(4)、長度(1)、小數位(1)、保留(14) |
| 資料區 | 檔頭長度 | 記錄長度×筆數 | 每筆以 0x20 (空白) 開頭作刪除旗標 |
| FoxPro 型別 | SQL*Loader 格式 | Oracle 型別 |
|---|---|---|
| Character (C) | CHAR | CHAR(n) |
| Logical (L) | CHAR | CHAR(1) ('T'/'F') |
| Numeric (N) 無小數 | INTEGER EXTERNAL NULLIF = BLANKS | NUMBER(p) |
| Numeric (N) 有小數 | DECIMAL EXTERNAL NULLIF = BLANKS | NUMBER(p,s) |
| Date (D) | DATE "YYYYMMDD" NULLIF = BLANKS | DATE |
#include
#include
#include
#include
#include
using namespace std;
#pragma pack(1)
struct DBF_HEADER {
uchar flag; uchar date[3]; ulong recCount;
ushort headLen; ushort recLen; uchar reserved[20];
};
struct DBF_FIELD {
char name[11]; uchar type; ulong offset;
uchar len; uchar dec; uchar reserved[14];
};
#pragma pack()
int main(int argc, char** argv) {
if (argc != 2) { cerr << "Usage: load \n"; return 1; }
char base[64]; strcpy(base, argv[1]);
// 1. 讀取 DBF 檔頭與欄位定義
FILE* fp = fopen(strcat(strcpy(new char[64], base), ".dbf"), "rb");
DBF_HEADER hdr; fread(&hdr, sizeof(hdr), 1, fp);
int fldCount = (hdr.headLen - 1) / 32 - 1;
DBF_FIELD* flds = new DBF_FIELD[fldCount];
for (int i=0; i
自動解析 DBF 結構產生 SQL*Loader 三件組,消除手工位置計算錯誤,將遷移效率提升數十倍。同樣原理可擴充至 dBase、Clipper、Visual FoxPro 等 XBase 系列資料庫遷移專案。