shp系列(六)——利用C++进行Dbf文件的写(创建)
发布日期:2022-02-10 11:37:03 浏览次数:46 分类:技术文章

本文共 6563 字,大约阅读时间需要 21 分钟。

上一篇介绍了shp文件的创建,接下来介绍dbf的创建。

推荐结合读取dbf的博客一起看!

推荐结合读取dbf的博客一起看!

推荐结合读取dbf的博客一起看!

 

1.Dbf头文件的创建

Dbf头文件的结构如下:

记录项数组说明:

字段类型说明:

关于每项的具体含义参照读取dbf文件的解释,这里重点解释几项:

  • HeaderByteNum指dbf头文件的字节数,数值不用除于2,具体为:从version到Reserved2(共32) + n个字段 * 每一个字段长度 32 + terminator。
  • RecordByteNum指每条记录的字节数,RecordByteNum根据记录的实际长度来写数值不用除于2,具体为:∑每个字段的字节数(字段数量根据读取打开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的创建。

转载地址:https://blog.csdn.net/Fan_z_0802/article/details/85175563 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:shp系列(五)——利用C++进行shp文件的写(创建)
下一篇:shp系列(七)——利用C++进行Shx文件的写(创建)

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年03月15日 01时25分01秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

java guava 使用_Java8-Guava实战示例 2021-06-24
python barrier option pricing_《Python金融数据分析》书内代码实战与讲解(二)金融衍生物定价... 2019-04-21
java自带工具_深入了解Java JDK自带工具,包括javac、jar、jstack等,实用~ 2019-04-21
gnome mysql client_解决MySQLWorkbenchgnome-keyring-daemon错误的方法分享 2019-04-21
java线程占用CPU_在windows下揪出java程序占用cpu很高的线程并完美解决 2019-04-21
java多态替换switch_使多态性无法解决那些switch / case语句的麻烦 2019-04-21
java httpclient 进度条_如何使用Apache HttpClient 4获取文件上传的进度条? 2019-04-21
下列不属于java语言特点的是_下列选项中,不属于Java语言特点的一项是( )。... 2019-04-21
java中小数的乘法_javascript的小数点乘法除法实例 2019-04-21
kappa一致性检验教程_SPSS在线_SPSSAU_Kappa一致性检验 2019-04-21
linux shell mysql备份_linux shell 备份mysql 数据库 2019-04-21
Java双向链表时间复杂度_链表是什么?有多少种链表?时间复杂度是? 2019-04-21
unity3d能和java系统整合吗_Android与Unity3d的整合 2019-04-21
minecraft666java_我的世界的666的世界 2019-04-21
辽宁师范大学java_辽宁师范大学心理学院 2019-04-21
java程序有连接数据库_Java程序连接数据库 2019-04-21
java reduce.mdn_reduce高级用法 2019-04-21
java shape用法_Java PShape.scale方法代码示例 2019-04-21
java字符串三目_java字符串连接运算符和三目运算符 2019-04-21
java 堆内存 非堆内存_JVM 堆内存和非堆内存 2019-04-21