How to read DBF files directly with Pro * C

xiaoxiao2021-03-06  65

To read the DBF file directly using C language programming, you need to know the binary format of the DBF file, and give a brief description below.

Table file consists of head records and data records. Header Defines the structure of the table and contains additional information related to the table. The header starts by the file position 0. Data Record 1 After the header record (continuous bytes), contains the actual text in the field.

The length of the record is equal to the sum of the lengths defined by all fields. The lower byte is in front of the table file.

1. The structure of the header record:

Byte offset

0 file type

0x02foxbase

0x03foxbase / dbase III Plus, no note

0x30Visual FoxPro

0x43dBase IV SQL table file, no note

0x63DBase IV SQL system file, no note

0x83foxbase / dbase III Plus, have a note

0x8BDBase IV has a note

0xcbdbase iv SQL table file, there is a note

0xF5foxPro 2.x (or earlier) has a note

0xfbfoxbase

1 - 3 Time for the latest update (YYMMDD)

Number of records in the 4 - 7 file

8 - 9 Location of the first data record

10 - 11 Length of each data record (including delete tag)

12 - 27 Reserved

28 table tag

0x01 file with .cdx structure

The 0x02 file contains a note.

0x04 file is a database (.dbc)

Note that this byte can contain any of the above values. For example, 0x03 indicates that the table has structured. CDX and a memo field.

29 code page tag

30 - 31 Reserved, including 0x00

32 - N field sub-record

The number of fields determines the number of field subcords. Each field in the table corresponds to a field sub-record.

N 1 header terminator (0x0D), N 2 to N 264 263 bytes within this range contain back chain information (relative paths of the related database (.dbc)). If the first byte is 0x00, the file is not associated with the database. Therefore, the database file itself always contains 0x00.

The first records in the 1st record indicate the starting position of the data in the data file. Data records start from the divided byte. If this byte is ASCII space (0x20), the record does not delete the tag, if the first byte is an asterisk (0x2a), the record has a delete tag. After the tag is the data in the field named in the field record

2. Field subcord structure

Byte offset

0 - 10 field name (up to 10 characters - if less than 10 empty characters (0x00) populate)

11 field type

C-character type

Y-currency type

N-numerical type

F-floating point

D-date type

T-date duration

B-double precision type

I-integer

L-logical type

M-memo

G-general type

C-character type (binary)

M- Remarks (binary)

P-picture type

12 - 15 Record the offset of this field

16 field length (in bytes)

17 decimal number

18 field tag

0x01 system column (user is not visible)

0x02 can store columns of NULL values

0x04 binary column (only suitable for characters and memos)

19 - 32 Reserved

Saved file header:

Support NULL value

Date Time, Money and Double Precision Data

Character field and note field mark as binary

Add a table in a database (.dbc) file

The prompts you can use the following formula: (x - 296/32) formula: (x - 296/32) formula, x represents the position of the first record (the 8th to 9th bytes of the header record), 296 263 (Rear Chain Information) 1 (Head Recording Terminator) 32 (First Field Sub Record), 32 is the length of the field sub-record. Because the record of the DBF file is stored in the file data section, it is stored in the ASCII code, so as long as the content of the file header and field type description area can be read directly, each record in the DBF file, the DBF file header structure And the field type description structure is represented by C language as follows:

Struct DBF_HEAD {/ * DBF file header structure * /

Char vers; / * version logo * /

Unsigned char yy, mm, dd; / * Last year, month, day * /

Unsigned long no_recs; / * file contains total record number * /

Unsigned short head_len, rec_len; / * File head length, record length * /

Char Reserved [20]; / * Reserved * /

}

STRUCT FIELD_ELEMENT {/ * field description structure * /

Char field_name [11]; / * field name * /

Char field_type; / * Field type * /

Unsigned long offset; / * Offset * /

Unsigned char field_length; / * field length * /

Unsigned char field_decimal; / * floating point number integer part length * /

Char reserved1 [2]; / * Reserved * /

Char dbaseiv_id; / * DBASE IV Work Area ID * /

Char reserved2 [10]; / *

CHAR Production_index;

}

It should be noted that the input DBF file is the version of the FoxPro 2.5 for DOS / Windows. The unsigned long and unsigned short fields indicating the number of records in the file header. The address order is from the high to the low; and the C program is in HP- When compiled under the UX operating system, the address order of the RISC CPU used by the HP server is opposite to the address order of the Intel X86 Series CPU. It is necessary to reverse the read unsigned long and unsigned shorts in the program. Operation, you can use bit operation programming:

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

FigSt = second = third = forth = * a;

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

((Second & 0x0000FF00) << 8) |

((Third & 0x00FF0000) >> 8) |

((Forth & 0xFF000000) >> 24);

}

According to the analysis of the DBF file format, use Pro * C programming, you can easily implement the function of reading the DBF file directly. The specific source code appendix is ​​as follows: #include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define nfields 5

#define True 1

#define false 0

/ * DBF file header structure * /

Struct DBF_HEAD {

Char Vers; / * Version Identifier * /

Unsigned char yy, mm, dd; / * yymmdd * /

Unsigned int No_recs; / * records number * /

Unsigned short head_len, rec_len; / * head_length, record_length * /

Char reserved [20]; / * reserved bytes * /

}

/ * DBF field description structure * /

Struct Field_Element {

Char Field_name [11];

Char Field_Type;

Unsigned int offset

UNSIGNED Char Field_Length;

UNSIGNED CHAR FIELD_DECIMAL;

Char reserved1 [2];

CHAR DBASEIV_ID;

Char reserved2 [10];

CHAR Production_index;

}

Char * dbf_fields_name [nfields] = {

"a", "b", "c", "d", "e"

}

/ * Global variable * /

Struct DBF_HEAD FILE_HEAD;

Struct Field_Element * Fields;

Int * Length;

Unsigned int * offset;

/ * Function protestal declaration * /

Void REVERT_UNSIGNED_SHORT (UNSIGNED SHORT * A);

Void Revert_unsigned_int (unsigned int * a);

Void REVERT_UNSIGNED_SHORT (unsigned short * a)

{

UNSIGNED SHORT LEFT, RIGHT;

LEFT = Right = * a;

* a = ((Left & 0x00FF) << 8) | ((Right & 0xFF00) >> 8);

}

Void Revert_unsigned_INT (unsigned int * a)

{

Unsigned int first, second, third, forth;

FigSt = second = third = forth = * a;

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

((Second & 0x0000FF00) << 8) |

((Third & 0x00FF0000) >> 8) |

((Forth & 0xFF000000) >> 24);

}

Int main (int Argc, char * argv [])

{

Register Int i, j;

File * fp_dat;

Char * buffer;

Char * allspace;

INT FIELDS_COUNT, MATCHED = FALSE;

Unsigned int counts;

IF ((fp_dat = fopen ("a.dbf", "rb")) == null) {fprintf (stderr, "cannot open dbf file to read! / n");

Exit (1);

}

FSeek (fp_dat, 0l, seek_set);

FREAD ((void *) & file_head, sizeof (struct dbf_head), 1, fp_dat);

Revert_unsigned_int (& File_Head.NO_RECS);

Revert_unsigned_short (& File_Head.Head_Len);

Revert_unsigned_short (& File_Head.Rec_len);

Fields_count = (file_head.head_len-sizeof (struct dbf_head) -1) / sizeof (struct field_element);

IF ((Struct Field_Element *) Malloc (Struct Field_Element) * Fields_count) == NULL) {

FPRINTF (stderr, "cannot allocate memory for fields array! / n");

Fclose (fp_dat);

EXIT (2);

}

IF ((buffer = (char *) malloc (sizeof (char) * file_head.rec_len) == null) {

FPrintf (stderr, "cannot allocate memory for record buffer! / n");

Fclose (fp_dat);

EXIT (3);

}

IF ((allspace = (char *) malloc (sizeof (char) * file_head.rec_len) == null) {

FPRINTF (stderr, "cannot allocate memory for all_space record buffer! / n");

Fclose (fp_dat);

EXIT (4);

}

Else {

MEMSET ((void *) allspace, '/ x20', file_head.rec_len-1);

Allspace [file_head.rec_len] = '/ 0';

}

FREAD ((void *) fields, sizeof (struct field_element), fields_count, fp_dat;

For (i = 0; i

Revert_unsigned_int (& Fields [i] .offset);

Fields [0] .offset = 1;

For (i = 1; i

Fields [i] .offset = fields [i-1] .offset (unsigned short) fields [i-1] .field_length;

Length = (int *) malloc (intend * fields_count);

OFFSET = (unsigned int *) malloc (sizeof (unsigned int) * fields_count);

IF (length == null || offset == null) {

FPrintf (stderr, "cannot allocate memory for array length);

EXIT (-1);

}

For (i = 0; i

{

For (j = 0; J

{

IF (strcmp (dbf_fields_name [i], fields [j] .field_name) == 0)

{

OFFSET [I] = fields [j] .offset - 1;

Length [i] = fields [j] .field_length;

Match = true;

Break;

}

IF (! matched) {

FPRINTF (stderr, "DBF file structure is invalid, field% s not found./N",

DBF_FIELDS_NAME [I]);

EXIT (-1);

}

Else

Match = false;

}

}

FSeek (fp_dat, (long) file_head.head_len, seek_set);

For (counts = 0; counts

{

IF (FGETC (fp_dat) == (int) '/ x2a')

{

FSeek (fp_dat, (int) file_head.rec_len-1, seek_cur);

CONTINUE;

}

FREAD ((void *) buffer, (int) file_head.rec_len-1, 1, fp_dat);

Buffer [file_head.rec_len] = '/ 0';

IF (strcmp (buffer, allspace) == 0) / * Remove full of record lines

CONTINUE;

/ * Further handle data in BUFFER * /

}

Fclose (fp_dat);

Free (buffer);

Free (allspace);

Free (Offset);

Free (Length);

Return 0;

}

转载请注明原文地址:https://www.9cbs.com/read-110911.html

New Post(0)