上一篇介绍了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的创建。

shp系列(六)——利用C++进行Dbf文件的写(创建)的更多相关文章

  1. shp系列(三)——利用C++进行DBF文件的读(打开)

    1.DBF文件要点 DBF文件又叫属性文件,也叫dBASE文件,文件后缀是.dbf,实际上ArcGIS打开后的属性表就是DBF的信息.DBF文件遵循以下几个条件: 每个要素在表中必须要包含一个与之相对 ...

  2. shp系列(七)——利用C++进行Shx文件的写(创建)

    之前介绍了Shp文件和Dbf的写(创建),最后来介绍一下Shx文件的写(创建).Shx文件是三者之中最简单的一个,原因有两个:第一是Shx文件的头文件与Shp文件的头文件几乎一样(除了FileLeng ...

  3. python常识系列07-->python利用xlwt写入excel文件

    前言 读书之法,在循序而渐进,熟读而精思.--朱熹 抽空又来写一篇,毕竟知识在于分享! 一.xlwt模块是什么 python第三方工具包,用于往excel中写入数据:(ps:只能创建新表格,不能修改表 ...

  4. PB导出规定格式DBF文件

    最近在做一个给卫计委做数据上报的数据接口,接口要求使用奇葩的dBase 3数据库存储上报数据,忙活了几天总算搞好了,使用开发工具为powerbuild 12,222个字段的上报数据表生成DBF文件,写 ...

  5. PB导出规定格式DBF文件 dBase 3 格式 222个字段

    最近在做一个给卫计委做数据上报的数据接口,接口要求使用奇葩的dBase 3数据库存储上报数据,忙活了几天总算搞好了,使用开发工具为powerbuild 12,222个字段的上报数据表生成DBF文件,写 ...

  6. shp系列(五)——利用C++进行shp文件的写(创建)

    之前介绍了shp文件.dbf文件和shx文件的的读取,接下来将分别介绍它们的创建过程.一般来说,读和写的一一对应的,写出的文件就是为了保存数据供以后读取的.写的文件要符合shapefile的标准.之前 ...

  7. shp系列(一)——利用C++进行shp文件的读(打开)与写(创建)开言

    博客背景和目的 最近在用C++写一个底层的东西,需要读取和创建shp文件.虽然接触shp文件已经几年了,但是对于shp文件内到底包含什么东西一直是一知半解.以前使用shp文件都是利用软件(如ArcGI ...

  8. shp系列(二)——利用C++进行shp文件的读(打开)

    1.各数据类型及其字节数 BYTE 1;       char 1;    short 2;      int 4;    double 8; 2.位序big和little及其转换 对于位序是big的 ...

  9. Java读取Level-1行情dbf文件极致优化(3)

    最近架构一个项目,实现行情的接入和分发,需要达到极致的低时延特性,这对于证券系统是非常重要的.接入的行情源是可以配置,既可以是Level-1,也可以是Level-2或其他第三方的源.虽然Level-1 ...

随机推荐

  1. js 事件冒泡、事件捕获、stopPropagation、preventDefault

    转自:http://www.jb51.net/article/42492.htm (1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. IE 5.5: ...

  2. DHCP 和 MDT 分开服务器的设置方法

    DHCP设置 043:供应商特定信息:01 04 00 00 00 00 FF 060:PXEClient:PXEClient 066:启动服务器主机名:IP 067:启动文件名:\Boot\x86\ ...

  3. Visual Studio 2015 开发 Linux 和树莓派 程序的 C++环境

    可以创建 树莓派 和 linux控制台应用. 创建后的 readme , 有各个设置的说明 你需要输入你虚拟主机, 编译环境linux虚拟机  的简单配置,另外, 4月5日的版本 如果 你的linux ...

  4. 团体程序设计天梯赛-练习集-*L1-043. 阅览室

    L1-043. 阅览室 天梯图书阅览室请你编写一个简单的图书借阅统计程序.当读者借书时,管理员输入书号并按下S键,程序开始计时:当读者还书时,管理员输入书号并按下E键,程序结束计时.书号为不超过100 ...

  5. Xilinx 7系列FPGA部分重配置【2】

    在之前的“Xilinx 7系列FPGA部分重配置[1]”中已经较为详细地记录了分别在工程模式(Project Mode)和非工程模式(Non-Project Mode)下.使用7系列的Xilinx F ...

  6. Django 框架入门

    1.创建虚拟环境.(如果你想在你的服务器中运行多个项目,那么装虚拟环境是最好的选择) pip install virtualenv pip install virtualenvwrapper 安装好后 ...

  7. vue-cli index.js dev 配置中 assetsPublicPath 的值不能填 "./" 的问题

    问题 使用nginx又代理了一层 在浏览器中 / 代表域名的根目录,./代表当前路径 线上发布的时候一般都会使用nginx反向代理,所以使用./是最靠谱的,但是vue-cli dev 中的 asset ...

  8. XX-Net的完整教程

    1.下载谷歌浏览器,安装. 2.百度搜索github,github中搜索XX-Net,下载稳定版 3.解压缩下载的文件夹,运行start.vbs文件.如果弹出管理员请求权限请允许,弹出防火墙警告,请允 ...

  9. 通过JDBC取Oracle数据库的时间字段时,时间丢失,只剩日期

    通过JDBC连接Oracle数据库,在查询的时候发现时间字段取出来值后只剩下了日期,时间消失了.查资料发现跟Oracle jdbc驱动版本有关,这里先贴出解决方案: 修改数据库的连接方式: try { ...

  10. python3使用465端口发送邮件来解决阿里云封闭25端口问题

    import smtplibfrom email.mime.text import MIMETextfrom email.utils import formataddr #发件人邮箱账号my_send ...