|
The following C/C++ example demonstrates the use of the FATS  indexing commands:
"C" Create Indexfile (Creates a index file with the specified characteristics.) | |
"O" Open Indexfile (Makes a index file available for access.) | |
"K" Close Indexfile (Releases a index file from availability.) | |
"I" Insert Record (Insert a new record.) | |
"F" Search First (Gets the key value and record number of the data record with the first key value.) | |
"L" Search Last (Gets the key value and record number of the data record with the last key value.) | |
"N" Search Next (Gets the key value and record number of the data record following the current record.) | |
"A" Search Next After (Gets the key value and record number of the data record whose key value is greater than the requested key value.) | |
"E" Search Previous Before (Gets the key value and record number of the data record whose key value is less than the requested key value.) | |
"Y" Auto Refresh (Specifies file locking and cache modes in single- and multi-user environments.) |
/* FATS 02.30 (c) GCS Software, Udo Gertz 1993-1998 Test program (Microsoft C/C++, Visual C) Build the test data file customer.dat. 19-03-2009 U.Gertz */ #include <stdio.h> #include <io.h> #include <fcntl.h> #include <sys\types.h> #include <sys\stat.h> #include <stdlib.h> #include <string.h> #include <memory.h> #include "FATS.h" /* Needed Object Files =================== To link FATS to your programs you will need the following object modules: FATS.OBJ The FATS module for DOS FATS_MCS.OBJ Interface / Small-model FATS_MCM.OBJ Interface / Medium-model FATS_MCC.OBJ Interface / Compact-model FATS_MCL.OBJ Interface / Large-model The following libraries are included on the distribution diskette to call the FATS Workstation Engine: FATSMCSR.LIB Interface / Small-model FATSMCMR.LIB Interface / Medium-model FATSMCCR.LIB Interface / Compact-model FATSMCLR.LIB Interface / Large-model If you want to make calls to the extended version of FATS (FATSXWE.EXE), you have to use the libraries FATSXCSR.LIB (small), FATSXCMR.LIB (medium), FATSXCCR.LIB (compact) or FATSXCLR.LIB (large). Linking a Microsoft C Program with FATS ======================================= To compile and link a application that calls FATS, use ONE of the following methods: 1. METHOD: Linking FATS to the program CL /c /A[?] /Ot TST1_ENG.C LINK TST1_ENG FATS_MC[?].OBJ FATS.OBJ [?] == s (small model), m (medium), c (compact), l (large) 2. METHOD: Calling the Workstation Engine (FATS_WE.EXE) CL /c /A[?] /Ot TST1_ENG.C LINK TST1_ENG FATSMC[?]R.LIB or if you own the extended version of FATS: (FATSXWE.EXE) LINK TST1_ENG FATSXC[?]R.LIB Calling FATS ============ All commands provided by FATS can be executed with one function: unsigned long FATSCALL(char *szCmnd, unsigned short *uFATSError, char *szReturnKey); The meaning of the used parameters: szCmnd With this command string you specify the actual FATS command. The available commands are described in the user manual. nErrorcode Your application must always pass this variable as the status parameter on a FATS call. After the FATS call, the application should always check the value of this variable. FATS returns a errorcode of 0 after a successful operation. FATS indicates any errors which occur during processing by returning a nonzero value in the errorcode variable. In the manual you can find a list of all FATS errorcodes and their possible causes. szReturnKey This variable will contain the key value of a found key after any normal search command (S,G,F,L,N,P,A,E). Return Value: Record Number */ struct custdat { char DELETEDMARK; char ID[6]; char NAME[26]; char JOB[26]; char STREET[26]; char ZIP[6]; char CITY[21]; }; char szCmnd[256]; char szFATSkey[256]; unsigned short uFATSError; unsigned long dwFATSRecno; struct custdat cust; main () { char cChar; int hCustomer; int hDemodata; int nCount = 0; int nIOresult; printf( "\nThis Test Program was designed for Microsoft C\n\n" ); printf( "To compile and link the test program, use ONE of the following methods:\n\n" ); printf( " 1. METHOD: Linking FATS to the program\n\n" ); printf( " CL /c /A[?] /Ot TST1_ENG.C\n" ); printf( " LINK TST1_ENG FATS_MC[?].OBJ FATS.OBJ;\n" ); printf( " [?] memory model: S (small) , M (medium), C (compact), L (large)\n\n" ); printf( " 2. METHOD: Calling the Workstation Engine\n\n" ); printf( " CL /c /A[?] /Ot TST1_ENG.C\n" ); printf( " LINK TST1_ENG FATSMC[?]R.LIB; \t(to call FATS_WE.EXE)\n\n" ); printf( " or if you own the extended version of FATS:\n\n" ); printf( " LINK TST1_ENG FATSXC[?]R.LIB; \t(to call FATSXWE.EXE)\n\n" ); printf( "Please press the [ENTER] key ...\n" ); cChar = getchar(); /* -------> Activation of Network Operation FATS is standardly equiped for the network environment. Nearly all commands can be executed both in single workstation and network environment. With the "Y" Auto Refresh command you determine the behavior of FATS accessing all index files. Normally it is sufficient to apply this instruction one time at the program start whereby the specified access mode will apply to all coming opened files, i.e. they are accessed either with network (Y\2) or single workstation access (Y\0). */ // dwFATSRecno = FATSCALL( "Y\\2", &uFATSError, szFATSkey ); /* -------> Open file with test data */ hDemodata = open( "..\\..\\..\\DEMODATA\\CUSTOMER.ASC", O_BINARY|O_RDONLY ); /* -------> create data file */ printf( "Creating Data File ...\n" ); hCustomer = creat( "CUSTOMER.DAT", S_IREAD|S_IWRITE ); setmode( hCustomer, O_BINARY ); /* -------> Create index file */ /* "C" Create Indexfile With this command you create an index file, whereby a possibly already existing file with the same name is deleted. After the file is created it will be opened with the opening flags defined with the command Auto Refresh (Y) and can be accessed under the file number you specified. Max. 200 primary keys per data record can be administered in an index file, the max. key length amounts to 240 characters. Full path names must be specified using forward slashes (/) instead of Backslashes (\), because FATS normally uses the Backslash character as delimiter. You may change the delimiters by placing the desired character as the first character of the command string, e.g. szCmnd = "&C&C:\ARTICLES.KEY&1&1&A&1". Any character with an Ascii code less then 48 will be accepted. The syntax of the command string: szCmnd = "C\{Filename}\{KeyLength}\{KeyCount}\{KeyType}\{FileNo}" FileName filename, perhaps with an additional path (e.g. C:/DATA/ARTICLES.KEY or ARTICLES.KEY) KeyLength Maximum key length (1-250) If you choose to have more than one key for this index file, you may specify the length for each key (separated by a semicolon ";") to conserve diskette space. Otherwise, the maximum length applies to all keys, i.e. every key will occupy the maximum space. KeyCount Number of primary keys (1-200) KeyType Key type (A = Ascii text, I = Integer) FileNo File number (1-40) */ printf( "Creating Index File ...\n\n" ); dwFATSRecno = FATSCALL( "C\\CUSTOMER.KEY\\5;25\\4\\A\\1", &uFATSError, szFATSkey ); /* ======================================================================== Insert Records ======================================================================== */ printf( "290 records will be inserted into the data file.\n" ); printf( "For each record 4 keys will be stored in the index file.\n" ); printf( "Please press the [ENTER] key ...\n" ); cChar = getchar(); memset( &cust, 0, sizeof( cust ) ); do { nIOresult = read( hDemodata, &cust.ID, 5 ); nIOresult = read( hDemodata, &cust.NAME, 25 ); nIOresult = read( hDemodata, &cust.JOB, 25 ); nIOresult = read( hDemodata, &cust.STREET, 25 ); nIOresult = read( hDemodata, &cust.ZIP, 5 ); if ( read( hDemodata, &cust.CITY, 20 ) == 20 ) { /* "I" Insert Record This command is used to insert the primary keys of a new data record into the index file. After the insert, the record number of the new record is returned in the "RECNO" variable. You can use this record number to write the data record to the data file. The number of keys included in the command string must equal the number of primary keys you specified in the Create Indexfile (C) command. The length of the transferred keys may not exceed the maximum key length specified with the Create Indexfile (C) command. Variable length keys will be padded with the Ascii char 0 to the maximum key length. The syntax of the command string: szCmnd = "I\{FileNo}\{KeyStr1}[\{KeyStr2}[\{KeyStr3}]]" FileNo File number KeyStr# Key value */ sprintf( szCmnd, "I\\1\\%s\\%s\\%s\\%s%s", cust.ID, cust.NAME, cust.JOB, cust.ZIP, cust.CITY ); dwFATSRecno = FATSCALL( szCmnd, &uFATSError, szFATSkey ); if ( uFATSError == 0 ) { printf( "%s --> RecNo %lu\n", cust.NAME, dwFATSRecno ); lseek( hCustomer, (dwFATSRecno - 1) * sizeof(cust), SEEK_SET ); nIOresult = write( hCustomer, &cust, sizeof(cust) ); } } nCount++; } while ( ( nCount < 290 ) && ( uFATSError == 0 ) ); close( hDemodata ); /* "K" Close Indexfile This command closes the index file with the specified file number. If you have activated the cache algorithm with the command Auto Refresh (Y), the possibly still in the cache buffers presented data are automatically written on the disk. If the cache is inactive after every FATS command all changed data are written on the disk. Therefore closing of a file is necessary only before terminating the application. If you omit the parameter "FileNo", then all opened index files are closed. This version is recommended before the termination of the application program. The syntax of the command string: szCmnd = "K\{FileNo}" FileNo File number */ dwFATSRecno = FATSCALL( "K\\1", &uFATSError, szFATSkey ); /* ======================================================================== Search ======================================================================== */ /* "O" Open Indexfile With this command you open an existing index file with the opening flags defined with the command Auto Refresh (Y). After the file was opened it can be accessed under the file number you specified. An index file already opened with the same file number is closed before this command is executed. Full path names must be specified using forward slashes (/) instead of Backslashes (\), because FATS normally uses the Backslash character as delimiter. You may change the delimiters by placing the desired character as the first character of the command string, e.g. szCmnd = "&O&C:\ARTICLES.KEY&1". Any character with an Ascii code less then 48 will be accepted. The syntax of the command string: szCmnd = "O\{FileName}\{FileNo}" Filename filename, perhaps with an additional path (e.g. C:/DATEN/ARTICLES.KEY or ARTICLES.KEY) FileNo File number */ dwFATSRecno = FATSCALL( "O\\CUSTOMER.KEY\\1", &uFATSError, szFATSkey ); /* -------> Print all customers, sorted in ascending order by NAME */ printf( "\n\n" ); printf( "This list shows some fields from the Customer Table,\n" ); printf( "sorted in ascending alphabetical order on the Customers\n" ); printf( "surname and forename.\n" ); printf( "Please press the [ENTER] key ...\n" ); cChar = getchar(); /* "F" Search First This command enables your application to retrieve the record number corresponding to the first key value for the specified key number. The syntax of the command string: szCmnd = "F\{KeyNo}\{FileNo}" KeyNo Key number FileNo File number */ strcpy( szCmnd, "F\\2\\1" ); do { dwFATSRecno = FATSCALL( szCmnd, &uFATSError, szFATSkey ); if ( uFATSError == 0 ) { lseek( hCustomer, (dwFATSRecno - 1) * sizeof(cust), SEEK_SET ); if ( read(hCustomer, &cust, sizeof(cust)) == sizeof(cust) ) { printf( "%s %s --> RecNo %lu\n", cust.NAME, cust.JOB, dwFATSRecno ); } /* "A" Search Next After With this command your application can retrieve the record number corresponding to the first key value which is greater than the key value you specify. If a duplicate key exists, the next higher record number of the next duplicate will be returned. The key value you specify with "KeyString" don't have to be a valid key in the index file. Unlike the "Search Next" command, this command can be used in a network environment. The syntax of the command string: szCmnd = "A\{KeyNo}\{RecNo}\{FileNo}\{KeyString}" KeyNo Key number RecNo Record number FileNo File number KeyString Key value */ sprintf( szCmnd, "A\\2\\%lu\\1\\%s", dwFATSRecno, szFATSkey ); } } while ( uFATSError == 0 ); /* --------> print all customers, sorted in ascending order by JOB */ printf( "\n\n" ); printf( "Two columns - JOB and NAME are displayed, sorted in ascending\n" ); printf( "order by the JOB field.\n" ); printf( "Please press the [ENTER] key ...\n" ); cChar = getchar(); strcpy( szCmnd, "F\\3\\1" ); do { dwFATSRecno = FATSCALL( szCmnd, &uFATSError, szFATSkey ); if ( uFATSError == 0 ) { lseek( hCustomer, (dwFATSRecno - 1) * sizeof(cust), SEEK_SET ); if ( read(hCustomer, &cust, sizeof(cust)) == sizeof(cust) ) { printf( "%s %s --> RecNo %lu\n", cust.JOB, cust.NAME, dwFATSRecno ); } /* "N" Search Next With this command your application can retrieve the record number corresponding to the first key value which is greater than the key value recently returned by one of the search commands, which have to be executed as the latest command. If a duplicate key exists, the next higher record number of the next duplicate will be returned. Each modification of the index file by inserting or deletion of keys makes an internal pointer invalid that is necessary for this instruction. You better use the command Search Next After (A) because this can happen in the network environment from any station. If there is no key in sequence FATS will return an errorcode of 15. The syntax of the command string: szCmnd = "N\{FileNo}" FileNo File number */ strcpy( szCmnd, "N\\1" ); } } while ( uFATSError == 0 ); /* --------> print list with records sorted by ZIP and CITY */ printf( "\n\n" ); printf( "Three columns - ZIP, CITY and NAME are displayed, sorted in\n" ); printf( "descending order by ZIP then CITY.\n\n" ); printf( "Please press the [ENTER] key ...\n" ); cChar = getchar(); /* "L" Search Last This command enables your application to retrieve the record number corresponding to the last key value for the specified key number. If duplicates exist for the last key value, the record number returned identifies the last duplicate, that is, the one inserted most recently. The syntax of the command string: szCmnd = "L\{KeyNo}\{FileNo}" KeyNo Key number FileNo File number */ strcpy( szCmnd, "L\\4\\1" ); do { dwFATSRecno = FATSCALL( szCmnd, &uFATSError, szFATSkey ); if ( uFATSError == 0 ) { lseek( hCustomer, (dwFATSRecno - 1) * sizeof(cust), SEEK_SET ); if ( read(hCustomer, &cust, sizeof(cust)) == sizeof(cust) ) { printf( "%s %s %s --> RecNo %lu\n", cust.ZIP, cust.CITY, cust.NAME, dwFATSRecno ); } /* "E" Search Previous Before With this command your application can retrieve the record number corresponding to the first key value which is less than the key value you specify. If a duplicate key exists, the next lower record number of the previous duplicate will be returned. The key value you specify with "KeyString" don't have to be a valid key in the index file. Unlike the "Search Prev" command, this command can be used in a network environment. The syntax of the command string: szCmnd = "E\{KeyNo}\{RecNo}\{FileNo}\{KeyString}" KeyNo Key number RecNo Record number FileNo File number KeyString Key value */ sprintf( szCmnd, "E\\4\\%lu\\1\\%s", dwFATSRecno, szFATSkey ); } } while ( uFATSError == 0 ); /* --------> Close index file */ dwFATSRecno = FATSCALL( "K\\1", &uFATSError, szFATSkey ); close( hCustomer ); }
© 2008 GCS Software, Udo Gertz