做ppt好的模板下载网站有哪些,唐山哪里有建设网站,素材下载解析接口网站开发,农业科技公司网站模板愿你出走半生,归来仍是少年#xff01; 环境#xff1a;.NET FrameWork4.5、.Net 6 1.简述 在地理信息系统中#xff0c;有很多的常用数据格式#xff0c;类似Shapefile、Dxf等等#xff0c;在不同的商业或开源平台中都有对其可靠的支持。DBF数据文件作为Shapefile文件的… 愿你出走半生,归来仍是少年 环境.NET FrameWork4.5、.Net 6 1.简述 在地理信息系统中有很多的常用数据格式类似Shapefile、Dxf等等在不同的商业或开源平台中都有对其可靠的支持。DBF数据文件作为Shapefile文件的属性存储文件出现的情况特别多除此之外现如今特别多的测绘公司对于数据的内业处理也还是保存在DBF中通过VFP进行处理。 虽然都是DBF文件但是其内部存在不同的文件类型这个会导致现如今在Git上找到的开源库有时候会出现有些dbf在打开时出现错误的情况。为了能够方便、快捷的读写DBF数据不少开发者需要安装驱动通过OLE DB的方式连接操作。 本文通过二进制流的方式进行DBF文件的解析、读取、写入同时说明DBF文件的构成。
1.1.C#依赖知识
C#数据类型字节数 数据类型所占字节数Byte1Short2Int4Char1 后续的文件读写操作都是基于C#中的BinaryReader进行。 2.DBF构成 每个DBF文件依次存在以下几个部分头文件区域、字段描述区域、后链信息VFP存在其它版本没发现、数据内容区域。 通过一下代码创建面向指定DBF文件的流读取器
new BinaryReader(new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read, 100000));
2.1.头文件区域 头文件区域共计占32字节具体分布如下。
文件头结构 字节范围字节数读取类型说明01Byte文件类型11Byte文件最后修改日期年 YY21Byte文件最后修改日期月 MM31Byte文件最后修改日期日 DD4-74Int数据记录数量总行数8-92Short文件头的字节长度头文件区域、字段描述区域、结束符0x0D、后链信息VFP存在其它版本没发现10-112short每一行数据记录的字节长度12-2716未使用保留区域281Byte表的标记 291Byte Language Driver ID (LDID),文件编码代码页标记30-312未使用保留区域
2.1.1.文件类型读取 // 获取Dbf的第一个字节代表dbf文件类型参照 DbfFileType 0FileType reader.ReadByte(); 创建BinaryReader后通过 ReadByte()方法读取文件第一个字节获取到Dbf的文件类型具体类型清单如下通过对比可得知当前的DBF类型。
DBF文件类型 编码说明0x02 FoxBASE0x03FoxBASE/dBASE III PLUS无备注0x30 Visual FoxPro0x43 dBASE IV SQL 表文件无备注0x63 dBASE IV SQL 系统文件无备注0x83 FoxBASE/dBASE III PLUS有备注0x8B dBASE IV 有备注0xCB dBASE IV SQL 表文件有备注0xF5 FoxPro 2.x或更早版本有备注0xFB FoxBASE 2.1.2.最后修改日期读取 // 获取更新日期年 1int year reader.ReadByte();// 获取更新日期月 2int month reader.ReadByte();// 获取更新日期日 3int day reader.ReadByte();try{//转换为日期UpdateDate new DateTime(year 1900, month, day);}catch{//获取文件的最后一次编辑时间UpdateDate new FileInfo(Filename).LastWriteTime;} 通过三次的ReadByte()方法依次读取出年月日并转换为对应的日期。当出错时就以文件的最后编辑时间作为参照。
2.1.3.数据记录数量/总行数 // 读取数据总数int 4字节长度 4-7NumRecords reader.ReadInt32(); 通过ReadInt32()方法一次性读取4个字节获得该DBF文件中现有的数据记录总数。
2.1.4.文件头总字节长度 // 读取文件的头文件长度 short 2字节长度 8-9HeaderLength reader.ReadInt16(); 通过ReadInt16()方法一次性读取2个字节获得该DBF文件的头文件总字节长度。
2.1.5.每行数据的字节长度 // 读取每行记录的长度 short 2字节长度 10-11RecordLength reader.ReadInt16(); 通过ReadInt16()方法一次性读取2个字节获得该DBF文件中每一行数据记录的长度。
2.1.6.保留区、标记 // 跳过系统保留区域 12-27 表的标记 28reader.ReadBytes(17);
2.1.7.代码页标记 // 读取 Language Driver ID (LDID) byte 1字节长度 29LanguageDriverId reader.ReadByte(); 通过ReadByte()方法读取代码页标记用于设置编码。
2.1.8.保留区
// 跳过系统保留区 30-31
reader.ReadBytes(2);
2.2.字段描述区域 字段描述区域包含了该DBF中的所有字段信息。每个字段的信息占用共计32字节长度然后以0x0d结束。若该DBF包含后链信息则后续是后链信息若不包含后链信息则后续是数据内容区域。 每个字段的信息32字节长度分布结构如下
2.2.1.字段名称读取
// 读取字段名称 字段名10字节0-9保留区默认为0,1字节10
string name Encoding.GetString(reader.ReadBytes(11));//获取保留区序号
int nullPoint name.IndexOf((char)0);//裁剪
if (nullPoint ! -1)
{name name.Substring(0, nullPoint);
}通过读取前面11个字节然后获取第一个0的位置进行裁剪获得名称。
2.2.2.字段类型读取 // 字段类型1字节11char code (char)reader.ReadByte(); 获取字段类型后可得知其对应的数据类型具体类型如下
2.2.3.字段偏移量读取
// 字段偏移量int 4字节12-15
int dataAddress reader.ReadInt32(); 2.2.4.字段长度读取
// 字段长度,byte 1字节 16
byte tempLength reader.ReadByte(); 2.2.5.字段小数位数读取
// 小数位数,byte 1字节 17
byte decimalcount reader.ReadByte(); 2.2.6.标记及保留区读取 // 字段标记及保留区 字段标记 byte 1字节 18,保留区 19-31reader.ReadBytes(14); 2.2.7.字段描述区整体读取 Fields new ListDbfField();bool readFieldFinish false;while (!readFieldFinish){// 读取字段名称 字段名10字节0-9保留区默认为0,1字节10string name Encoding.GetString(reader.ReadBytes(11));//获取保留区序号int nullPoint name.IndexOf((char)0);//裁剪if (nullPoint ! -1){name name.Substring(0, nullPoint);}// 字段类型1字节11char code (char)reader.ReadByte();// 字段偏移量int 4字节12-15 int dataAddress reader.ReadInt32();// 字段长度,byte 1字节 16byte tempLength reader.ReadByte();// 小数位数,byte 1字节 17byte decimalcount reader.ReadByte();// 字段标记及保留区 字段标记 byte 1字节 18,保留区 19-31reader.ReadBytes(14);DbfField myField new DbfField(name, code, tempLength, decimalcount){DataAddress dataAddress};Fields.Add(myField);dt.Columns.Add(myField);long pst reader.BaseStream.Position;//_numFields (HeaderLength - FileDescriptorSize - 1) / FileDescriptorSize;// 字段描述区的结束符 0x0d有些版本后面有263个字节包含后链信息相关数据库 (.dbc) 的相对路径。// 计算字段数量【头长度-文件描述长度32-结束符长度1】/单字段描述区长度32进行计算会忽略263字符的情况// 如果第一个字节为 0x00则该文件不与数据库关联。因此数据库文件本身总是包含 0x00。byte last reader.ReadByte();if (last 0x0d){readFieldFinish true;}else{reader.BaseStream.Position pst;}} 整体读取时需要注意的是每次读取完成后需要进行下一个字节的判断当这个字节是0x0d时就代表字段描述区域已经完结了。这样的话可以避过后链信息区域的干扰获取到正确的字段集合。
2.3.数据内容区域 字段描述区域包含了该DBF中的所有数据记录每条记录的字节长度固定为2.1.5中获取到的每行数据的字节长度每个字段的长度为2.2.4.中获取到的字段长度。通过字节长度读取每个字段对应的数据内容并根据在2.2.2.中获取的字段类型进行转换便可以获取到对应的数据。 每条记录的第一个字节都是该记录的删除标记当内容为空格 (0x20)时表示该记录未标记删除当内容为星号 (0x2A)时表示该记录已标记为删除。