shp系列(六)——利用C++進行Dbf檔案的寫(建立)
阿新 • • 發佈:2018-12-22
上一篇介紹了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的建立。