上一篇介紹了shp文件的創建,接下來介紹dbf的創建。
推薦結合讀取dbf的博客一起看!
推薦結合讀取dbf的博客一起看!
推薦結合讀取dbf的博客一起看!
1.Dbf頭文件的創建
Dbf頭文件的結構如下:

記錄項數組說明:

字段類型說明:

關於每項的具體含義參照讀取dbf文件的解釋,這里重點解釋幾項:
- HeaderByteNum指dbf頭文件的字節數,數值不用除於2,具體為:從version到Reserved2(共32) + n個字段 * 每一個字段長度 32 + terminator。
- RecordByteNum指每條記錄的字節數,數值不用除於2,RecordByteNum根據記錄的實際長度來寫,具體為:∑每個字段的字節數(字段數量根據讀取打開shp的字段數決定)。例如我的例子中寫了八個字段,則一條記錄的實際長度為:1(deleteFlag) + 10 + 32 + 16 + 10 + 10 + 8 + 19 + 19 = 1 + 124 =125。
2.Dbf記錄實體的創建
記錄實體就是每條記錄,一個記錄有多個字段,部分字段上存儲必要的信息。由於實際上每個shp文件的表的字段數可能不一樣,並且每個字段的類型不固定,需要每次判定字段類型,然后根據不同類型設置來輸出信息。
但是這費時費力,根據實際情況,簡化一下,讀取已知字段數和字段類型的DBF的信息,或者說,根據實際需要的字段數和字段類型來輸出,犧牲普遍性來獲取快速結果,以后修改也不困難。
3.創建Dbf的代碼
void WriteDbf(CString filename)
{
//創建與Shp文件同名的指針
int n = filename.ReverseFind('.');
filename = filename.Left(n);
filename = filename + ".dbf";
FILE* m_DbfFile_fp;
if ((m_DbfFile_fp = fopen(filename, "wb")) == NULL)
return;
//****創建dbf文件的文件頭
int i, j;
BYTE version = 4;
fwrite(&version, 1, 1, m_DbfFile_fp);
CTime t = CTime::GetCurrentTime();
int d = t.GetDay();
int y = t.GetYear() % 2000;
int m = t.GetMonth();
BYTE date[3];
date[0] = y;
date[1] = m;
date[2] = d;
for (i = 0; i<3; i++) //記錄時間
fwrite(date + i, 1, 1, m_DbfFile_fp);
int RecordNum = map->layer->objects.size(); //文件中的記錄條數
fwrite(&RecordNum, sizeof(int), 1, m_DbfFile_fp);
short HeaderByteNum = 0; //文件頭中的字節數,暫時寫0,后面要返回來修改
fwrite(&HeaderByteNum, sizeof(short), 1, m_DbfFile_fp);
short RecordByteNum = 0; //一條記錄中的字節長度,暫時寫0,后面要返回來修改
fwrite(&RecordByteNum, sizeof(short), 1, m_DbfFile_fp);
short Reserved1 = 0;
fwrite(&Reserved1, sizeof(short), 1, m_DbfFile_fp);
BYTE Flag4s = 0;
fwrite(&Flag4s, sizeof(BYTE), 1, m_DbfFile_fp);
BYTE EncrypteFlag = 0;
fwrite(&EncrypteFlag, sizeof(BYTE), 1, m_DbfFile_fp);
int Unused[3] = { 0,0,0 };
for (i = 0; i<3; i++)
fwrite(Unused + i, sizeof(int), 1, m_DbfFile_fp);
BYTE MDXFlag = 0;
fwrite(&MDXFlag, sizeof(BYTE), 1, m_DbfFile_fp);
BYTE LDriID = 0;
fwrite(&LDriID, sizeof(BYTE), 1, m_DbfFile_fp);
short Reserved2 = 0;
fwrite(&Reserved2, sizeof(short), 1, m_DbfFile_fp);
//****寫記錄項數組
int fieldscount = fieldscount_final; //字段數量可以根據讀取的shp文件確定
for (i = 0; i< fieldscount; i++)
{
RecordItem recordItem = recordItems[i]; //recordItems是自己設置的記錄項數組(字段)的數組,
//根據需求設定每個記錄項數組(字段)的參數,以供調用
//****name--------11 bytes
fwrite(recordItem.name, 11, 1, m_DbfFile_fp);
//****FieldType----1 bytes
fwrite(&(recordItem.fieldType), sizeof(BYTE), 1, m_DbfFile_fp);
//****Reserved3----4 bytes
fwrite(&(recordItem.Reserved3), sizeof(int), 1, m_DbfFile_fp);
//****FieldLength--1 bytes
fwrite(&(recordItem.fieldLength), sizeof(BYTE), 1, m_DbfFile_fp);
//****DecimalCount-1 bytes
fwrite(&(recordItem.decimalCount), sizeof(BYTE), 1, m_DbfFile_fp);
//****Reserved4----2 bytes
fwrite(&(recordItem.Reserved4), sizeof(short), 1, m_DbfFile_fp);
//****WorkID-------1 bytes
fwrite(&(recordItem.workID), sizeof(BYTE), 1, m_DbfFile_fp);
//****Reserved5----10 bytes
for (j = 0; j<5; j++)
fwrite(recordItem.Reserved5 + j, sizeof(short), 1, m_DbfFile_fp);
//****MDXFlag1-----1 bytes
fwrite(&(recordItem.mDXFlag1), sizeof(BYTE), 1, m_DbfFile_fp);
}
BYTE terminator = 13; //頭文件終止標識符
fwrite(&terminator, sizeof(BYTE), 1, m_DbfFile_fp);
fseek(m_DbfFile_fp, 8, SEEK_SET); //轉到頭文件字節數RecordByteNum,開始重寫
HeaderByteNum = 32 + 32 * fieldscount + 1; //從version到Reserved2(共32) + n個字段 * 每一個字段長度 32 + terminator
fwrite(&HeaderByteNum, sizeof(short), 1, m_DbfFile_fp);
RecordByteNum = 1 + 124; //RecordByteNum根據記錄的實際長度來寫,∑每個字段的長度
// 1 + 10 + 32 + 16 + 10 + 10 + 8 + 19 + 19 = 1 + 124 =125
fseek(m_DbfFile_fp, 10, SEEK_SET); //轉移每條記錄長度RecordByteNum
fwrite(&RecordByteNum, sizeof(short), 1, m_DbfFile_fp);
fseek(m_DbfFile_fp, 0, SEEK_END);
//****寫dbf文件頭結束
//****寫每條記錄
BYTE deleteFlag;
char media[40];
for (i = 1; i <= RecordNum; i++){
CGeoPolygon* polygon = (CGeoPolygon*)map->layer->objects[i - 1];
deleteFlag = 32; //默認寫32
fwrite(&deleteFlag, sizeof(BYTE), 1, m_DbfFile_fp); //讀取刪除標記 1字節
//****寫 ObjectID int
stringstream ss;
ss << (i - 1);
string str = ss.str();
int length = str.length();
memset(media, '\0', 40);
for (int m = 0; m < 10 - length; m++)
media[m] = ' ';
for (int c = 10 - length; c < 10; c++)
media[c] = str[c - 10 + length];
for (j = 0; j<10; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--10
//****寫Dest string
memset(media, '\0', 40);
media[0] = '/';
for (int c = 1; c <32; c++)
media[c] = ' ';
for (j = 0; j<32; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--32
//****寫Ec string
for (j = 0; j<16; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--16
//****寫EcRm int
ss << -8888;
str = ss.str();
length = str.length();
memset(media, '\0', 40);
for (int m = 0; m < 10 - length; m++)
media[m] = ' ';
for (int c = 10 - length; c < 10; c++)
media[c] = str[c - 10 + length];
for (j = 0; j<10; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--10
//****寫Elevt int
for (j = 0; j<10; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--10
//****寫Cc int
str = polygon->objectAttribute;
memset(media, '\0', 40);
length = str.length();
for (int c = 0; c < length; c++)
media[c] = str[c];
for (int c = length; c < 8; c++)
media[c] = ' ';
for (j = 0; j<8; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--8
//****寫shape_length double
CString str1;
double shape_length = polygon->getAllLength();
str1.Format(_T("%.11e"), shape_length);
memset(media, '\0', 40);
media[0] = ' ';
for (int c = 1; c < 16; c++)
media[c] = str1[c - 1];
if (str1.GetLength() == 18)
for (int c = 16; c < 19; c++)
media[c] = str1[c - 1];
else {
media[16] = '0';
media[17] = str1[15];
media[18] = str1[16];
}
//*(media + length ) = '\0';
for (j = 0; j<19; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--19
//****寫shape_Area double
double shape_area = polygon->shapeArea;
str1.Format(_T("%.11e"), shape_area);
memset(media, '\0', 40);
media[0] = ' ';
for (int c = 1; c < 16; c++)
media[c] = str1[c - 1];
if (str1.GetLength() == 18)
for (int c = 16; c < 19; c++)
media[c] = str1[c - 1];
else {
media[16] = '0';
media[17] = str1[15];
media[18] = str1[16];
}
for (j = 0; j<19; j++)
fwrite(media + j, sizeof(char), 1, m_DbfFile_fp); //--19
}
//****寫dbf文件記錄結束
fclose(m_DbfFile_fp);
}
下一篇將介紹Shx的創建。
