关于DBF文件格式的详细说明

    技术2022-05-20  35

    最近要做一个程序,数据源是DBF的,用Java去解析它,结果发现有问题,网上找了相关资料,发现这个资料对里面的结构将的还是蛮细的,对我帮助也是蛮大的。转载自:http://blog.csdn.net/wyp_810618/archive/2010/04/14/5485212.aspx

    转载到自己的空间是为了查找方便,在此向原文的作者表示感谢。以下是正文内容

    DBF 文件结构:

    表文件由头记录及数据记录组成。头记录定义该表的结构并包含与表相关的其他信息。头记录由文件位置 0 开始。数据记录1紧接在头记录之后(连续的字节),包含字段中实际的文本。  记录的长度(以字节为单位)等于所有字段定义的长度之和。表文件中存储整数时低位字节在前。  1.表头记录的结构:  字节偏移 说明  0 文件类型  0×02FoxBASE  0×03FoxBASE+/dBASE III PLUS,无备注  0×30Visual FoxPro  0×43dBASE IV SQL 表文件,无备注  0×63dBASE IV SQL 系统文件,无备注  0×83FoxBASE+/dBASE III PLUS,有备注  0×8BdBASE IV 有备注  0xCBdBASE IV SQL 表文件,有备注  0xF5FoxPro 2.x(或更早版本)有备注  0xFBFoxBASE  1 – 3 最近一次更新的时间(YYMMDD)  4 – 7 文件中的记录数目  8 – 9 第一个数据记录的位置  10 – 11 每个数据记录的长度(包括删除标记)  12 – 27 保留  28 表的标记  0×01具有 .cdx 结构的文件  0×02文件包含备注。  0×04文件是数据库(.dbc)  请注意,这个字节可以包含任何上面值的和。例如,0×03 表明表具有结构化.cdx和一个备注字段。 29 代码页标记 30 – 31 保留,包含 0×00  32 – n 字段子记录  字段的数目决定了字段子记录的数目。表中每个字段都对应一个字段子记录。  n+1 头记录终止符(0×0D),n+2 到 n+264 此范围内的 263 个字节包含后链信息(相关数据库 (.dbc) 的相对路径)。如果第一个字节为 0×00,则该文件不与数据库关联。因此数据库文件本身总是包含 0×00。  1 头记录中的第 8 到第 9 个字节指示数据文件中数据的起始位置。数据记录从 除标记字节开始。如果此字节为 ASCII 空格 (0×20),该记录没有删除标记, 如果第一字节为星号 (0×2A),该记录有删除标记。在标记之后是字段记录中所命名各字段中的数据 2.字段子记录结构 字节偏移 说明 0 – 10 字段名(最多 10 个字符 -若少于 10 则用空字符 (0×00) 填充) 11 字段类型  C-字符型  Y-货币型  N-数值型  F-浮点型  D-日期型  T-日期时间型  B-双精度型  I-整型  L-逻辑型 M-备注型  G-通用型  C-字符型(二进制) M-备注型(二进制) P-图片型  12 – 15 记录中该字段的偏移量  16 字段长度(以字节为单位)  17 小数位数  18 字段标记 0×01系统列(用户不可见) 0×02可存储 null 值的列  0×04二进制列(只适于字符型和备注型) 19 – 32 保留  格式保存的文件标头: 支持 null 值  日期时间型、货币型及双精度型数据 字符字段和备注字段标记为二进制 在数据库 (.dbc) 文件中添加表 提示 可以使用下面的公式求出表文件中字段的数目:(x – 296/32) 公式中,x 表示第一个记录的位置(表头记录的第 8 到第 9 个字节),296 表示 263(后链信息)+ 1(头记录终止符)+ 32(第一个字段子记录),32 是字段子记录的长度。

    文件头数据结构描述(C和Pascal) 描述

    因为dbf文件的记录在文件数据部分,都是用ASCII码形式存放的,所以只要读出文件头和字段类型描述区的内容,就可以直接读取dbf文件中的每条记录,dbf文件头结构和字段类型描述

    文件头数据结构描述(C和Pascal)

    C 描述

    因为dbf文件的记录在文件数据部分,都是用ASCII码形式存放的,所以只要读出文件头和字段类型描述区的内容,就可以直接读取dbf文件中的每条记录,dbf文件头结构和字段类型描述结构用C语言表示如下: struct dbf_head { /* DBF文件头结构 */ char vers; /* 版本标志*/ unsigned char yy,mm,dd; /* 最后更新年、月、日 */ unsigned long no_recs; /* 文件包含的总记录数 */ unsigned short head_len,rec_len; /* 文件头长度,记录长度 */ char reserved[20]; /* 保留 */ }; struct field_element{ /* 字段描述结构 */ char field_name[11]; /* 字段名称 */ char field_type; /* 字段类型 */ unsigned long offset; /* 偏移量 */ unsigned char field_length; /* 字段长度 */ unsigned char field_decimal; /* 浮点数整数部分长度 */ char reserved1[2]; /* 保留 */ char dbaseiv_id; /* dBASE IV work area id */ char reserved2[10]; /* char production_index;  }; 需 要注意的是,输入的dbf文件是FoxPro 2.5 for DOS/Windows的版本,文件头中表示记录数等内容的unsigned long和unsigned short字段,寻址顺序是从高位到低位;而C程序在HP-UX操作系统下编译时,HP服务器使用的RISC CPU的寻址顺序与Intel x86系列CPU的寻址顺序相反,是从低位到高位,故程序中需要将读取的unsigned long和unsigned short进行反转操作,可以使用位操作编程实现: void revert_unsigned_short(unsigned short *a) { unsigned short left,right; left=right=*a; *a=((left&0×00ff)<<8)|((right&0xff00)>>8); } void revert_unsigned_long(unsigned long *a) { unsigned long first,second,third,forth; first=second=third=forth=*a; *a=((first&0×000000ff)<<24)| ((second&0×0000ff00)<<8)| ((third&0×00ff0000)>>8)| ((forth&0xff000000)>>24); }

    这是我用Passcal描述的:

    Tdbf_head = packed record     vers : char ; //版本标志     yy,mm,dd :byte;  // 最后更新年、月、日     no_recs : longword ; // 文件包含的总记录数;     head_len,rec_len : word;  //文件头长度,记录长度     reserved : array[0..19] of char ;   end;   Tfield_element =record // 字段描述结构     field_name:array[0..10] of char; // 字段名称     field_type:char; // 字段类型     offset:longword; // 偏移量     field_length:byte; // 字段长度     field_decimal:byte; // 浮点数整数部分长度     reserved1:array[0..1] of char; // 保留     dbaseiv_id:char; // dBASE IV work area id     reserved2:array[0..9] of char; //     production_index:char;   end;

    附程序:

    附源码:

    结构用C语言表示如下: struct dbf_head { /* DBF文件头结构 */ char vers; /* 版本标志*/ unsigned char yy,mm,dd; /* 最后更新年、月、日 */ unsigned long no_recs; /* 文件包含的总记录数 */ unsigned short head_len,rec_len; /* 文件头长度,记录长度 */ char reserved[20]; /* 保留 */ }; struct field_element{ /* 字段描述结构 */ char field_name[11]; /* 字段名称 */ char field_type; /* 字段类型 */ unsigned long offset; /* 偏移量 */ unsigned char field_length; /* 字段长度 */ unsigned char field_decimal; /* 浮点数整数部分长度 */ char reserved1[2]; /* 保留 */ char dbaseiv_id; /* dBASE IV work area id */ char reserved2[10]; /* char production_index;  }; 需 要注意的是,输入的dbf文件是FoxPro 2.5 for DOS/Windows的版本,文件头中表示记录数等内容的unsigned long和unsigned short字段,寻址顺序是从高位到低位;而C程序在HP-UX操作系统下编译时,HP服务器使用的RISC CPU的寻址顺序与Intel x86系列CPU的寻址顺序相反,是从低位到高位,故程序中需要将读取的unsigned long和unsigned short进行反转操作,可以使用位操作编程实现: void revert_unsigned_short(unsigned short *a) { unsigned short left,right; left=right=*a; *a=((left&0×00ff)<<8)|((right&0xff00)>>8); } void revert_unsigned_long(unsigned long *a) { unsigned long first,second,third,forth; first=second=third=forth=*a; *a=((first&0×000000ff)<<24)| ((second&0×0000ff00)<<8)| ((third&0×00ff0000)>>8)| ((forth&0xff000000)>>24); }

    这是我用Passcal描述的:

    Tdbf_head = packed record     vers : char ; //版本标志     yy,mm,dd :byte;  // 最后更新年、月、日     no_recs : longword ; // 文件包含的总记录数;     head_len,rec_len : word;  //文件头长度,记录长度     reserved : array[0..19] of char ;   end;   Tfield_element =record // 字段描述结构     field_name:array[0..10] of char; // 字段名称     field_type:char; // 字段类型     offset:longword; // 偏移量     field_length:byte; // 字段长度     field_decimal:byte; // 浮点数整数部分长度     reserved1:array[0..1] of char; // 保留     dbaseiv_id:char; // dBASE IV work area id     reserved2:array[0..9] of char; //     production_index:char   end;


    最新回复(0)