常州市润邦电子科技有限公司

热保护器测试专业供应商

 

DBF的文件格式和C语言描述,表文件由头记录及数据记录组成。

DBF的文件格式和C语言描述,表文件由头记录及数据记录组成。

头记录定义该表的结构并包含与表相关的其他信息。头记录由文件位置   0   开始。
数据记录1紧接在头记录之后(连续的字节),包含字段中实际的文本。   记录的长度(以字节为单位)等于所有字段定义的长度之和。

表文件中存储整数时低位字节在前。    

1.表头记录的结构:    
字节偏移 说明   备注
0 文件类型 0x02 FoxBASE     0x03 FoxBASE+/dBASE   III   PLUS,无备注     0x30 Visual   FoxPro     0x43 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  
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,则该文件不与数据库关联。

备注:头记录中的第   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;    
};
 
 
 
 
/************************************************************************************
  COMMENTS:DBF文件的总体格式
a.数据记录部分,紧随结构描述部分,以ASCII码方式顺序存放,结束标志为1AH(即
    文件结束标志),每条记录的首字节为删除标志,20H表示有效,2AH表示已被删除,
      字段值间无分隔符,记录亦无结束标记.
b.结构描述部分,位于文件首部,以二进制方式存放,结束标志为0DH.长度
    为32*(数据库的字段个数+1(即库整体描述))+1(0DH结束标志)
  ************************************************************************************/

#include   <windows.h>
#include   <stdio.h>
#include   <stdlib.h>

//DBF   文件头结构//即库整体描述表,共32个字节
typedef   struct   tagDBFFILEHEADER
{
unsigned   char dfMark; //0x03h   或   0x80h(有MEMORY字段) 0
unsigned   char dfYear,dfMmonth,dfDay; //依次为年月日,二进制 1-3
unsigned   long dfRecordCount; //总记录个数,低位字节在前 4-7
unsigned   short dfHeaderLength; //文件头长度=第9字节值*256+第8字节值 8-9
unsigned   short dfRecordLength; //记录长度=第11字节值*256+第10字节值 10-11
unsigned   char dfReserved[20]; //保留 12-31
}DBFFILEHEADER;

//DBF   字段结构//即字段描述表,32个字节/字段
typedef   struct   tagDBFINFOHEADER
{
unsigned   char diFieldName[10]; //字段名称,ASCII码 0-9
unsigned   char diReserved1; //保留字节 10
unsigned   char diFieldType; //字段类型,CDNL等ASCII码 11
unsigned   long diOffset; //本字段在首记录中的位置 12-15
unsigned   char diFieldLength; //字段长度 <=256 16
unsigned   char diDecimal; //小数点的位数 17
unsigned   char diReserved[14]; //保留 18-31
}DBFINFOHEADER;

typedef   DBFFILEHEADER   *LPDBFFILEHEADER;
typedef   DBFINFOHEADER   *LPDBFINFOHEADER;


/************************************************************************************
  CDBFFile   class   defination.
************************************************************************************/
class   CDBFFile    
{
public:
CDBFFile();
virtual   ~CDBFFile();
long   InitDbf(LPCTSTR   lpszFilename); //填充FILEHEADER和INFOHEADER
int GetFieldCount();
int GetFieldLength(int   FieldNum);
int GetDecimal(int   FieldNum);
unsigned   char   *   GetFieldName(int   FieldNum);
unsigned   char GetFieldType(int   FieldNum);
long GetRecordCount();
int GetRecordLength();
int GetRecord(int   RecordNum,unsigned   char   *pBuf);
int GetRecordFieldValue(int   RecordNum,int   FieldNum,unsigned   char   *pBuf);
unsigned   long GetFieldColumSize(int   fieldnum);

public:
unsigned   char   *   m_Buffer;
DBFFILEHEADER m_FileHeader;
DBFINFOHEADER m_InfoHeader;
DWORD m_dwRecordLen;
};


 
 
 
/************************************************************************************
  COMMENTS:CDBFFile实现文件
************************************************************************************/

#include   "DBFFile.h "

//////////////////////////////////////////////////////////////////////
//   Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDBFFile::CDBFFile()
{
m_Buffer   =   NULL;
}

CDBFFile::~CDBFFile()
{
if(m_Buffer)   delete   []   m_Buffer;
m_Buffer   =   NULL;
}

/************************************************************************************
  FUNCTION:         初始化数据库
  PARAMETER:       [in]   lpszFilename   ---   指定要操作的DBF文件名
  RETURN   VALUE:void
************************************************************************************/
long   CDBFFile::InitDbf(LPCTSTR   lpszFilename)
{
HANDLE   hFile;
DWORD     dwFileSize,   dwReadBytes;
DWORD     dwErrCode;

hFile   =   CreateFile(lpszFilename,   GENERIC_READ,   FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,   OPEN_EXISTING,   FILE_ATTRIBUTE_NORMAL,   NULL);
if(hFile   ==   INVALID_HANDLE_VALUE)
{
dwErrCode   =   GetLastError();
GetErrorMsg(dwErrCode,   g_szErrMsg);
WriteLog( "Open   DBF   File   failed!\x0D\x0A ",   g_szErrMsg);
return   -1;
}

dwFileSize   =   GetFileSize(hFile,   NULL);
if(dwFileSize==0)
{
dwErrCode   =   GetLastError();
GetErrorMsg(dwErrCode,   g_szErrMsg);
WriteLog( "Get   File   size   failed!\x0D\x0A ",   g_szErrMsg);
CloseHandle(hFile);
return   -1;
}

if(m_Buffer)
{
delete   []   m_Buffer;
m_Buffer   =   NULL;
}
m_Buffer   =   new   unsigned   char[dwFileSize];
if(!m_Buffer)
{
WriteLog( "Allocate   memeory   failed   in   InitDbf()!\x0D\x0A ",   NULL);
CloseHandle(hFile);
return   -1;
}
ReadFile(hFile,   m_Buffer,   dwFileSize,   &dwReadBytes,   NULL);
memcpy((void*)&m_FileHeader,   m_Buffer,   sizeof(DBFFILEHEADER));
m_dwRecordLen   =   m_FileHeader.dfRecordLength;
CloseHandle(hFile);
return   0;
}

/************************************************************************************
  FUNCTION:         获取字段个数
  PARAMETER:       None
  RETURN   VALUE:字段个数
************************************************************************************/
int   CDBFFile::GetFieldCount()
{
return(m_FileHeader.dfHeaderLength/32   -   1);
}

/************************************************************************************
  FUNCTION:         获取任一字段名
  PARAMETER:       [in]   FieldNum   (base   1)
  RETURN   VALUE:字段名
************************************************************************************/
unsigned   char   *   CDBFFile::GetFieldName(int   FieldNum)
{
if   (FieldNum   <   1)   return   NULL;
unsigned   char   *   p   =   &(m_Buffer[FieldNum   *   32]);
memcpy(&m_InfoHeader,   p,   sizeof(m_InfoHeader));
return(m_InfoHeader.diFieldName);
}

/************************************************************************************
  FUNCTION:         获取任一字段长度
  PARAMETER:       [in]   FieldNum   (base   1)
  RETURN   VALUE:字段长度
************************************************************************************/
int   CDBFFile::GetFieldLength(int   FieldNum)
{
if   (FieldNum   <   1)   return   -1;
unsigned   char   *   p   =   &(m_Buffer[FieldNum   *   32]);
memcpy(&m_InfoHeader,   p,   sizeof(m_InfoHeader));
return(m_InfoHeader.diFieldLength);
}

/************************************************************************************
  FUNCTION:         获取任一字段类型
  PARAMETER:       [in]   FieldNum   (base   1)
  RETURN   VALUE:字段类型(A,N   and   so   on)
************************************************************************************/
unsigned   char   CDBFFile::GetFieldType(int   FieldNum)
{
if   (FieldNum   <   1)   return   '# ';  
unsigned   char   *   p   =   &(m_Buffer[FieldNum   *   32]);
memcpy(&m_InfoHeader,   p,   sizeof(m_InfoHeader));
return(m_InfoHeader.diFieldType);
}

/************************************************************************************
  FUNCTION:         获取任一数值型字段小数点位数
  PARAMETER:       [in]   FieldNum   (base   1)
  RETURN   VALUE:小数点位数
************************************************************************************/
int   CDBFFile::GetDecimal(int   FieldNum)
{
if   (FieldNum   <   1)   return   -1;
unsigned   char   *   p   =   &(m_Buffer[FieldNum   *   32]);
memcpy(&m_InfoHeader,   p,   sizeof(m_InfoHeader));
return(m_InfoHeader.diDecimal);
}

/************************************************************************************
  FUNCTION:         获取记录个数
  PARAMETER:       None
  RETURN   VALUE:获取记录个数
************************************************************************************/
long   CDBFFile::GetRecordCount()
{
return(m_FileHeader.dfRecordCount);
}

/************************************************************************************
  FUNCTION:         获取记录长度
  PARAMETER:       None
  RETURN   VALUE:记录长度
************************************************************************************/
int   CDBFFile::GetRecordLength()
{
return(m_FileHeader.dfRecordLength);
}

/************************************************************************************
  FUNCTION:         获取任一记录内容
  PARAMETER:       [in]   RecordNum   (base   1)记录索引
    [out]   *pBuf 记录内容
  RETURN   VALUE:参数错误返回0
    成功返回1
************************************************************************************/
int   CDBFFile::GetRecord(int   RecordNum,unsigned   char   *pBuf)
{
if   (RecordNum   <   1)   return   0;

long   lPos=m_FileHeader.dfHeaderLength   +   (RecordNum-1)   *   m_dwRecordLen;
//(DBFFILEHEADER+DBFINFOHEADER+头结束标志)+(RecordNum-1)*(记录长度)
unsigned   char   *   p   =   &(m_Buffer[lPos]);
memcpy(pBuf,   p,   m_dwRecordLen);
return   1;
}

/************************************************************************************
  FUNCTION:         获取任一记录的任一字段值
  PARAMETER:       [in]   RecordNum   (base   1)记录索引
    [in]   iFieldNum   (base   1)字段索引
    [out]   *pBuf 记录内容
  RETURN   VALUE:参数错误返回0
    成功返回1
************************************************************************************/
int   CDBFFile::GetRecordFieldValue(int   iRecordNum,int   iFieldNum,unsigned   char   *pBuf)
{
char   szLeft[100];
char   szRight[100];
int   i,   iFieldLen,   iBegin,   iFieldCount;

memset(szLeft,   0,   sizeof(szLeft));
memset(szRight,   0,   sizeof(szRight));
iFieldCount   =   GetFieldCount();
if(iRecordNum   <   1   ||   iFieldNum   <   1   ||   iFieldNum> iFieldCount)   return   0;

iFieldLen=GetFieldLength(iFieldNum);
int   iOffset=1; //记录的删除标志2AH/20H
for   (i=1;   i <iFieldNum;   i++)
{
iOffset+=GetFieldLength(i);
}
long   lPos=iOffset   +   m_FileHeader.dfHeaderLength+(iRecordNum-1)*GetRecordLength();
unsigned   char   *   p   =   &(m_Buffer[lPos]);
memcpy(pBuf,   p,   iFieldLen);
pBuf[iFieldLen]=0x0; //注意参数pBuf必须足够大(指定字段长度+1)
strcpy(szLeft,   (char   *)pBuf);
for(i=iFieldLen-1;   i> =0;   i--)
{
if(szLeft[i]= '   ')   szLeft[i]   =   0;
else   break;
}
if(szLeft[0]==0)
{
strcpy((char   *)pBuf,   szLeft);
return   1;
}
for(i=0;   i <iFieldLen;   i++)
{
if(szLeft[i]!= '   ')
{
iBegin   =   i;
break;
}
}
memcpy(szRight,   szLeft+iBegin,   iFieldLen-iBegin);
strcpy((char   *)pBuf,   szRight);

return   1;
}

/************************************************************************************
  FUNCTION:         获取字段宽度
  PARAMETER:       [in]   iFieldNum   (base   1)字段索引
  RETURN   VALUE:参数错误返回0
    成功返回字段宽度
************************************************************************************/
unsigned   long CDBFFile::GetFieldColumSize(int   fieldnum)
{
int   iFieldCount;

iFieldCount   =   GetFieldCount();
if   (fieldnum   <   1   ||   fieldnum> iFieldCount)   return   0;
return   GetFieldLength(fieldnum)   *   GetRecordCount();
}
 

posted on 2010-07-23 16:54  常州市润邦电子科技  阅读(1759)  评论(0编辑  收藏  举报

导航