2023年12月22日发(作者:)

DBF文件格式分析

DBF数据表文件的结构分析:

DBF文件由两部分组成,

第一部分是结构描述,即文件头信息;共32个字节(0~31)

第二部分是表本身的内容,该部分又分为两个部分:

前一部分是表的结构说明,共32个字节具体的内容见下表1

后一部分是字段描述区,从第32个字节开始到十六进制结束字符0x0D。具体包括内容见表2

1.表头记录的结构:

字节偏移 说明

0 文件类型

0x02FoxBASE

0x03FoxBASE+/dBASE III PLUS,无备注

0x30Visual FoxPro

0x43dBASE IV SQL 表文件,无备注

0x63dBASE IV SQL 系统文件,无备注

0x83FoxBASE+/dBASE III PLUS,有备注

0x8BdBASE IV 有备注

0xCBdBASE IV SQL 表文件,有备注

0xF5FoxPro 2.x(或更早版本)有备注

0xFBFoxBASE

解读:

低字节在前,所以要取字段总数时,应该用如下方法:

记录总数 = 第4个字节+256 1次方*第5字节+256 2*第6字节+256 3*第7字节

注意:

字段名 以ASCII码方式存放,最大长度是10个字符,若字段名长度少于10个字符则以空字符(0x00)填充

字段类型 以ASCII码方式存放,1个字符,其值为

Field type:

C – Character

Y – Currency

N – Numeric

F – Float

D – Date

T – DateTime

B – Double

I – Integer

L – Logical

M – Memo

G – General

C – Character (binary)

M – Memo (binary)

P – Picture

+ – Autoincrement (dBase Level 7)

O – Double (dBase Level 7)

@ – Timestamp (dBase Level 7)

DBF数据表文件的结构结束标志为"0x0D",占1个字节。对于VFP表文件从"0x0D"所在的字节开始的263B用于描述自由表或数据库表的相关信息(若为自由表则取值全为零)。

其VFP表文件长度 = 32(文件头)+32*字段个数+1(结束标志)+263。然后是数据部分记录1、记录2……记录n

各记录均为定长格式,以ASCII码方式顺序存放。

每个记录的第一个字节是删除标志,若记录被删除,则该字节为0x2A即"*";否则为0x20即空格。

各记录间无分隔符

整个文件的结束标志为0x1A,位于最后一个记录之后的一个字节中。

主要在于分析的2进制结构。

DBF文件由头记录及数据记录组成。头记录定义该表的结构并包含与表相关的其他信息。头记录由文件位置 0 开始。数据记录1紧接在头记录之后(连续的字节),包含字段中实际的文本。

记录的长度(以字节为单位)等于所有字段定义的长度之和。表文件中存储整数时低位字节在前。

1.表头记录的结构:

字节偏移 说明

0 文件类型

0x02FoxBASE

0x03FoxBASE+/dBASE III PLUS,无备注

0x30Visual FoxPro

0x43dBASE IV SQL 表文件,无备注

0x63dBASE IV SQL 系统文件,无备注

0x83FoxBASE+/dBASE III PLUS,有备注

0x8BdBASE IV 有备注

0xCBdBASE IV SQL 表文件,有备注

0xF5FoxPro 2.x(或更早版本)有备注

0xFBFoxBASE

1 - 3 最近一次更新的时间(YYMMDD)

4 - 7 文件中的记录数目

8 - 9 第一个数据记录的位置

10 - 11 每个数据记录的长度(包括删除标记)

12 - 27 保留

28 表的标记

0x01具有 .cdx 结构的文件

0x02文件包含备注。

0x04文件是数据库(.dbc)

请注意,这个字节可以包含任何上面值的和。例如,0x03 表明表具有结构化.cdx和一个备注字段。

29 代码页标记

30 - 31 保留,包含 0x00

32 - n 字段子记录

字段的数目决定了字段子记录的数目。表中每个字段都对应一个字段子记录。

n+1 头记录终止符(0x0D),n+2 到 n+264 此范围内的 263 个字节包含后链信息

(相关数据库 (.dbc) 的相对路径)。如果第一个字节为 0x00,则该文件不与数据库关联。因此数据库文件本身总是包含 0x00。

1 头记录中的第 8 到第 9 个字节指示数据文件中数据的起始位置。数据记录从 除标记字节开始。如果此字节为 ASCII 空格 (0x20),该记录没有删除标记, 如果第一字节为星号 (0x2A),该记录有删除标记。在标记之后是字段记录中所命名各字段中的数据

2.字段子记录结构

字节偏移 说明

0 - 10 字段名(最多 10 个字符 -若少于 10 则用空字符 (0x00) 填充)

11 字段类型

C-字符型

Y-货币型

N-数值型

F-浮点型

D-日期型

T-日期时间型

B-双精度型

I-整型

L-逻辑型

M-备注型

G-通用型

C-字符型(二进制)

M-备注型(二进制)

P-图片型

12 - 15 记录中该字段的偏移量

16 字段长度(以字节为单位)

17 小数位数

18 字段标记

0x01系统列(用户不可见)

0x02可存储 null 值的列

0x04二进制列(只适于字符型和备注型)

19 - 32 保留

格式保存的文件标头:

支持 null 值

日期时间型、货币型及双精度型数据

字符字段和备注字段标记为二进制

在数据库 (.dbc) 文件中添加表

提示 可以使用下面的公式求出表文件中字段的数目:(x - 296/32) 公式中,x 表示第一个记录的位置(表头记录的第 8 到第 9 个字节),296 表示 263(后链信息)+ 1(头记录终止符)+ 32(第一个字段子记录),32 是字段子记录的长度。

因为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&0x00ff) < <8)|((right&0xff00)> > 8);

}

void revert_unsigned_long(unsigned long *a)

{

unsigned long first,second,third,forth;

first=second=third=forth=*a;

*a=((first&0x000000ff) < <24)|

((second&0x0000ff00) < <8)|

((third&0x00ff0000)> > 8)|

((forth&0xff000000)> > 24);

}