📄 dbf.cpp
字号:
#ifdef XB_MEMO_FIELDS xbShort MemoSw = 0;#endif i = j = 0; DbfStatus = XB_CLOSED; /* Get the datafile name and store it in the class */ NameLen = strlen(TableName) + 1; if(( rc = NameSuffixMissing( 1, TableName )) > 0 ) NameLen += 4; DatabaseName = TableName; if( rc == 1) DatabaseName +=".dbf"; else if( rc == 2 ) DatabaseName += ".DBF"; /* check if the file already exists */ if((( fp = fopen( DatabaseName, "r" )) != NULL ) && !Overlay ){ fclose( fp ); xb_error(XB_FILE_EXISTS); } else if( fp ) fclose( fp ); if(( fp = fopen( DatabaseName, "w+b" )) == NULL ) xb_open_error(DatabaseName); #ifdef XB_LOCKING_ON /* no buffering in multi user mode */ setbuf( fp, NULL );#endif /* count the number of fields and check paramaters */ i = 0; while( s[i].Type != 0 ){ NoOfFields++; RecordLen += s[i].FieldLen; if( s[i].Type != 'C' && s[i].Type != 'N' && s[i].Type != 'F' && s[i].Type != 'D' &&#ifdef XB_MEMO_FIELDS s[i].Type != 'M' &&#endif /* XB_MEMO_FIELDS */ s[i].Type != 'L' ) xb_error(XB_UNKNOWN_FIELD_TYPE);#ifdef XB_MEMO_FIELDS if( !MemoSw && ( s[i].Type=='M' || s[i].Type=='B' || s[i].Type=='O')) MemoSw++;#endif// check for numeric fields which are too long if((s[i].Type == 'N' || s[i].Type == 'F') && s[i].FieldLen > 19 ) xb_error(XB_INVALID_FIELD_LEN); i++; } RecordLen++; /* add one byte for 0x0D */ if(( RecBuf = (char *) malloc( RecordLen )) == NULL ) { InitVars(); xb_memory_error; } if(( RecBuf2 = (char *) malloc( RecordLen )) == NULL ){ free( RecBuf ); InitVars(); xb_memory_error; } /* BlankRecord(); */ memset( RecBuf, 0x20, RecordLen ); memset( RecBuf2, 0x20, RecordLen ); /* set class variables */ Version = XFV & 0x7; // file version - bit 0-2#ifdef XB_MEMO_FIELDS if (MemoSw) { if(XFV & 0x7 == 3) Version |= 0x80; // memo presence - bit 7 else Version = 0x8b; }#endif CurRec = 0L; HeaderLen = 33 + NoOfFields * 32; xbDate d; UpdateYY = (d.YearOf() - 1900); if(XFV & 0x7 == 3) UpdateYY %= 100; // dBASE III seems to do this, but IV does not. DTB UpdateMM = d.MonthOf(); UpdateDD = d.DayOf( XB_FMT_MONTH ); /* write the header prolog */ if(( rc = WriteHeader( 0 )) != XB_NO_ERROR ){ free( RecBuf ); free( RecBuf2 ); fclose( fp ); InitVars(); xb_error(XB_WRITE_ERROR); } count = 20;#ifdef XB_REAL_DELETE if(RealDelete) count = 12;#endif#if 0 for( i = 0; i < count; i++ ) { if(( fwrite( "\x00", 1, 1, fp )) != 1 ) { free( RecBuf ); free( RecBuf2 ); fclose( fp ); InitVars(); xb_error(XB_WRITE_ERROR); } }#endif if((SchemaPtr=(xbSchemaRec *)malloc(NoOfFields*sizeof(xbSchemaRec)))==NULL){ free( RecBuf ); free( RecBuf2 ); fclose( fp ); InitVars(); xb_memory_error; } memset( SchemaPtr, 0x00, ( NoOfFields * sizeof(xbSchemaRec))); /* write the field information into the header */ for( i = 0, k = 1; i < NoOfFields; i++ ){// next two lines updated 9/14/99 - reported by Piotr Klaban// if field name too long ( > 10 bytes ) then SIGSEGV errors memset( SchemaPtr[i].FieldName, 0x00, 11 ); strncpy( SchemaPtr[i].FieldName, s[i].FieldName, 10 ); SchemaPtr[i].Type = s[i].Type; if( s[i].Type == 'M' || s[i].Type == 'B' || s[i].Type == 'O' ) { /* memo fields are always 10 bytes */ SchemaPtr[i].FieldLen = 10; SchemaPtr[i].NoOfDecs = 0; } else { SchemaPtr[i].FieldLen = s[i].FieldLen; SchemaPtr[i].NoOfDecs = s[i].NoOfDecs; } if( SchemaPtr[i].NoOfDecs > SchemaPtr[i].FieldLen ) { fclose( fp ); free( SchemaPtr ); free( RecBuf ); free( RecBuf2 ); InitVars(); xb_error(XB_INVALID_SCHEMA); } k2 = k; k += SchemaPtr[i].FieldLen; if(( fwrite( &SchemaPtr[i], 1, 18, fp )) != 18 ) { fclose( fp ); free( SchemaPtr ); free( RecBuf ); free( RecBuf2 ); InitVars(); xb_error(XB_WRITE_ERROR); } for( j = 0; j < 14; j++ ) { if(( fwrite( "\x00", 1, 1, fp )) != 1 ) { free( SchemaPtr ); free( RecBuf ); free( RecBuf2 ); fclose( fp ); InitVars(); xb_error(XB_WRITE_ERROR); } } SchemaPtr[i].Address = RecBuf + k2; SchemaPtr[i].Address2 = RecBuf2 + k2; } /* write the header terminator */// if(( fwrite( EofChar, 2, 1, fp )) != 1 ) { if(( fputc( XB_CHARHDR, fp )) != XB_CHARHDR ){ fclose( fp ); free( SchemaPtr ); free( RecBuf ); free( RecBuf2 ); InitVars(); xb_error(XB_WRITE_ERROR); }#ifdef XB_MEMO_FIELDS if( MemoSw ) if((rc = CreateMemoFile()) != XB_NO_ERROR) { fclose(fp); free(RecBuf); free(RecBuf2); InitVars(); xb_error(rc); }#endif DbfStatus = XB_OPEN; return xbase->AddDbfToDbfList(this, DatabaseName);}/************************************************************************///! Close the dbf file./*! This method attempts to close the XDB DBF file which was previously opened with either CreateDatabase() or OpenDatabase(). Deletes any memory allocated. Automatically closes any open indexes associated with this data file. \param deleteIndexes if TRUE, the indexes (xbIndex instances) will also be deleted (index files will not be deleted) \returns One of the following: \htmlonly <p> <table border=2><tr><th>Return Code</th><th>Description</th></tr> <tr><td>XB_NO_ERROR</td><td>No error</td></tr> <tr><td>XB_NOT_OPEN</td><td>File was not open</td></tr> </table> \endhtmlonly \latexonly \\ \\ \begin{tabular}{|l|l|} \hline \textbf{Return Code} & \textbf{Description} \\ \hline \hline XB\_NO\_ERROR & No Error \\ \hline XB\_NOT\_OPEN\_ERROR & File was not open \\ \hline \end{tabular} \endlatexonly*/xbShort xbDbf::CloseDatabase(bool deleteIndexes){#if defined(XB_INDEX_ANY) xbIxList *i, *ti;#endif if (DbfStatus == XB_CLOSED) xb_error(XB_NOT_OPEN); if (DbfStatus == XB_UPDATED /*&& AutoUpdate*/ ) { xbDate d; UpdateYY = d.YearOf() - 1900; if(XFV == 3) UpdateYY %= 100; // dBASE III seems to do this, IV does not. DTB UpdateMM = d.MonthOf(); UpdateDD = d.DayOf( XB_FMT_MONTH ); /* update the header */ WriteHeader( 1 ); /* write eof marker */ fseek( fp, 0L, 2 );// fwrite( EofChar, 1, 1, fp ); fputc( XB_CHAREOF, fp ); PutRecord( CurRec ); }#if defined(XB_INDEX_ANY) i = NdxList; while (i) { i->index->CloseIndex(); if(deleteIndexes) delete i->index; i = NdxList; }/* free up unused nodes */ i = FreeIxList; while( i ) { ti = i; i = i->NextIx; free(ti); }#endif if (SchemaPtr){ for( int j = 0; j < NoOfFields; j++ ) if( SchemaPtr[j].fp ) delete SchemaPtr[j].fp; free( SchemaPtr ); } if (RecBuf) free( RecBuf ); if (RecBuf2) free( RecBuf2 ); #ifdef XB_MEMO_FIELDS if (mbb) free( mbb ); /* memo block buffer */ if (mfp) fclose( mfp ); /* memo file pointer */#endif xbase->RemoveDbfFromDbfList( this ); fclose( fp ); InitVars(); return XB_NO_ERROR;}/************************************************************************//* options 1 = Print header only 2 = Field data only 3 = Header and Field data *///! Dump header information./*! \param Option One of the following: \htmlonly <p> <table border=2><tr><th>Option</th><th>Description</th></tr> <tr><td>1</td><td>Print header only</td></tr> <tr><td>2</td><td>Field data only</td></tr> <tr><td>3</td><td>Header and field data</td></tr> </table> \endhtmlonly \latexonly \\ \\ \begin{tabular}{|l|l|} \hline \textbf{Option} & \textbf{Description} \\ \hline \hline 1 & Header only \\ \hline 2 & Field data only \\ \hline 3 & Header and field data \\ \hline \end{tabular} \endlatexonly*/#ifdef XBASE_DEBUGxbShort xbDbf::DumpHeader( xbShort Option ){ int i; if( Option < 1 || Option > 3 ) xb_error(XB_INVALID_OPTION); if( DbfStatus == XB_CLOSED ) xb_error(XB_NOT_OPEN); cout << "\nDatabase file " << DatabaseName << endl << endl; if( Option != 2 ) { cout << "File header data:" << endl; if( Version == 3 ) cout << "Dbase III file" << endl; else if ( Version == 83 ) cout << "Dbase III file with memo fields" << endl << endl; cout << "Last update date = " << (int) UpdateMM << "/" << (int) UpdateDD << "/" << (int) UpdateYY % 100 << endl; cout << "Header length = " << HeaderLen << endl; cout << "Record length = " << RecordLen << endl; cout << "Records in file = " << NoOfRecs << endl << endl;#ifdef XB_REAL_DELETE cout << "First Free Rec = " << FirstFreeRec << endl << endl;#endif } if( Option != 1 ) { // cout << "Field Name Type Length Decimals" << endl; // cout << "---------- ---- ------ --------" << endl; for( i = 0; i <NoOfFields; i++ ) { if( SchemaPtr[i].Type == 'C' && SchemaPtr[i].NoOfDecs > 0 ) printf( "%10s %1c %4d %4d\n", SchemaPtr[i].FieldName, SchemaPtr[i].Type, SchemaPtr[i].FieldLen, 0 ); else printf( "%10s %1c %4d %4d\n", SchemaPtr[i].FieldName, SchemaPtr[i].Type, SchemaPtr[i].FieldLen, SchemaPtr[i].NoOfDecs ); } } cout << endl; return XB_NO_ERROR;}#endif/************************************************************************///! Open the DBF file./*! This method attempts to open the XDB DBF file with the specified name (TableName). This method does not position to any particular record in the file. The record buffer is blanked (set to spaces). \param TableName Name of table to open \returns One of the following: \htmlonly <p> <table border=2><tr><th>Return Code</th><th>Description</th></tr> <tr><td>XB_NO_ERROR</td><td>No error</td></tr> <tr><td>XB_OPEN_ERROR</td><td>Couldn't open file</td></tr> <tr><td>XB_NO_MEMORY</td><td>Memory allocation error</td></tr> <tr><td>XB_NOT_XBASE</td><td>Not an XDB DBF file</td></tr> </table> \endhtmlonly \latexonly \\ \\ \begin{tabular}{|l|l|} \hline \textbf{Return Code} & \textbf{Description} \\ \hline \hline XB\_NO\_ERROR & No error \\ \hline XB\_OPEN\_ERROR & Couldn't open file \\ \hline XB\_NO\_MEMORY & Memory allocation error \\ \hline XB\_NOT\_XBASE & Not an XDB DBF file \\ \hline \end{tabular} \endlatexonly*/xbShort xbDbf::OpenDatabase( const char * TableName ){ xbShort i, j, NameLen, rc; char buf[33]; char *p;#ifdef XB_MEMO_FIELDS xbShort MemoSw = 0;#endif /* verify the file is not already open */ if ( DbfStatus != XB_CLOSED ) xb_error(XB_ALREADY_OPEN); /* Get the datafile name and store it in the class */ NameLen = strlen( TableName ) + 1; if(( rc = NameSuffixMissing( 1, TableName )) > 0 ) NameLen += 4; /* copy the file name to the class variable */ DatabaseName = TableName; if( rc == 1) DatabaseName += ".dbf"; else if( rc == 2 ) DatabaseName += ".DBF"; /* open the file */ if(( fp = fopen(DatabaseName, "r+b")) == NULL ) xb_open_error(DatabaseName); #ifdef XB_LOCKING_ON /* no buffering in multi user mode - may not see what others have updated */ setbuf( fp, NULL );#endif#ifdef XB_LOCKING_ON if( AutoLock ) if(( rc = LockDatabase( F_SETLKW, F_RDLCK, 0L )) != XB_NO_ERROR) return rc;#endif /* copy the header into memory */ if(( rc = ReadHeader( 1 )) != XB_NO_ERROR ) { InitVars(); return rc; } /* check the version */ if( Version == 3 || Version == (char)0x83 ) /* dBASE III+ */ { XFV = 3;#ifdef XB_MEMO_FIELDS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -