home *** CD-ROM | disk | FTP | other *** search
- ********************************************************************************
- * PROC sdf2dbf (FOR FOXPRO) THE FAST VERSION
- *
- * SYNTAX:
- * DO sdf2dbf WITH ;
- * [<expC>], ; && dbf header template
- * [<expC>], ; && sdf ascii file to be converted to dbf format
- * [<expN>] && buffer size; allows between 64k & 256k buffer size
- *
- * PURPOSE: Converts IN-PLACE Standard Data Format (SDF) files TO .DBF file
-
- * This is great for those giant ascii files you download from your mainframe that
- * are too big to do an 'APPEND FROM' into a receiving .DBF file. sd2dbf.prg
- * performs in-place conversion of an SDF fixed-length ascii file to .DBF format.
- * All you need is a .DBF file with zero records as the header template file, and the
- * SDF file to be converted in-place. You may specify the dual buffer size from
- * 64k to 256k as a 3rd parameter, but I recommend sticking with 64k size buffers.
- * It verifies that the SDF table has no variable length records before continuing.
- * This is still a beta version, so not all the error traps are there....you've
- * been warned (i.e. make sure you have a few more spare bytes of disk lying around
- * in case the converted file has to grow a little)
-
- *
- * DANGER, WILL ROBINSON!
- * WARNING: The records in the SDF file *MUST* be FIXED LENGTH AND *MUST*
- * have and End-of-record marker like CR/LF or CR or LF. If the rec's
- * are variable length, use the SDF2DBF.PRG listed in the
- * DECEMBER '92 DataBased Advisor.
- * ALSO: if you think there may be CR's or LF's any where else
- * in the SDF file, DON'T DO THIS!
- *
- *
- * ADVANTAGE: If your SDF data is 100% FIXED LENGTH, this version of
- * SDF2DBF.PRG will run faster and doesn't require ADDITIONAL
- * DISK SPACE for work areas or exception processing. In lieu
- * of the record-by-record approach seen in Steve Freides DBA
- * SDF2DBF version, this one gobbles up the SDF rec's in 64 k chunks,
- * does a STRTRAN( big_ole_data_buffer, CHR(13)+CHR(10), " ")
- * to change the CR/LF's into the deletion field,
- * and keeps juggling both 64k buffers until it's done. (the
- * 2 data buffers are required becaused of the displacement caused
- * by introducing the DBF header to the top of the file)
-
- * Enjoy. -leebert
- *
- * COPYRIGHT: Released into public domain.
- *
- * Author: Lee Rodgers
- * leebert@io.com
- * 73144.2276@CompuServe.com
- *
- *
- ********************************************************************************
- *FUNCTION sdf2dbf
- PARAMETERS s_template_file, s_sdf_file, n_buff_bytes
-
- IF PARAMETERS() < 3 OR n_buff_bytes < 64000 OR n_buff_bytes > 256000
- n_buff_bytes = 64000 && conservative FP2.0 setting
- ENDIF
-
-
- IF PARAMETERS() < 2 OR EMPTY(s_template_file) OR EMPTY(s_sdf_file)
- ?? CHR(7) && BEEP!
- ?? CHR(7) && BEEP!
- WAIT WINDOW [2 paramters are required!]
- RETURN .F.
- ENDIF
- s_template_file = UPPER(s_template_file )
- s_sdf_file = UPPER(s_sdf_file)
-
- IF !all_ok()
- RETURN
- ENDIF
-
- STORE '' TO s_head_str
- STORE 0 TO n_rec_size, n_head_size, n_f_hand
- =get_template( @n_rec_size, @n_head_size, @n_f_hand, @s_head_str )
-
- STORE 0 TO n_SDF_hand, a_SDF_size, g_rec_size, a_rec_size
- STORE '' TO m_EOR1, m_EOR2, m_EOR_mark
- =get_sdf( @n_SDF_Hand, @a_SDF_size, @a_Rec_size, @g_rec_size, @m_EOR1, @m_EOR2, @m_EOR_mark )
-
- STORE 0 TO a_N_recs_expected
- IF !error_traps( @a_N_recs_expected )
- =FCLOSE( n_SDF_hand )
- RETURN .F.
- ENDIF
-
- IF !chk_sdf( n_SDF_Hand, a_SDF_size, a_Rec_size, g_rec_size, m_EOR_mark )
- WAIT WINDOW "There are variable length records in the SDF File."
- RETURN .F.
- ENDIF
-
- STORE 0 TO a_buff_size, a_buff_recs
- =get_buff_size( @a_buff_size, @a_buff_recs )
-
- =convert_loop()
-
- =adjust_fsize()
-
- RETURN
- *================================================================
- *
- * FUNCTION convert_loop
- *
- *================================================================
- FUNCTION convert_loop
-
- PRIVATE a_b1_end, n_counter, s_buff_1, s_buff_2, a_b2_end, a_b1_end, a_EOH_posit
-
- WAIT CLEAR
-
- STORE '' TO s_buff_1, s_buff_2
- STORE 0 TO a_b2_end, a_B1_end, a_EOH_posit
-
- a_b1_end = 0 && the file position marker for buffer # 1
- n_counter = 0 && today's show was brought to you by the numbers Σ n+1
-
- DO WHILE .T. AND (1=1) && i've actually seen someone seriously code this. " IF 1=1 "
- && question is: what happens when !(1 = 1) ?
- && a: reality as we know has ceased to exist!
-
- n_counter = n_counter + 1
-
- *--display on screen amount completed
- WAIT WINDOW NOWAIT ;
- STR( (a_b1_end / a_SDF_size * 100), 5,2) + [ % DONE ]
-
- *============================================================
- * ok. 1st time through: need to write in header, but
- * first, load up both buffers, then write header
- *============================================================
- IF n_counter = 1 && first time through:
- && write the header into the SDF file
- =write_header(@s_buff_1, @s_buff_2, @a_b2_end, @a_B1_end, @a_EOH_posit )
- ENDIF
-
- * steps
- * 1. goto old b1 (buffer 1) end
- * 2. write modified b1 (buffer 1) recs
- * 3. get new b1 end
- * 4. move b2 (buffer # 2) into b1 (buffer #1)
- * 5. goto old b2 end
- * 6. read new b2 SDF recs
- * 7. get new b2 end
- * 8. convert new b2 to DBF recs
-
- * 1. goto old b1 end
- nul = FSEEK( n_SDF_hand, a_B1_end, 0)
-
- *--if we're on the last records, get rid of
- *--the extra delete field and change it to a ^Z
- IF LEN(s_buff_2) = 0
- s_buff_1 = SUBSTR( s_buff_1, 1, LEN(s_buff_1)-2 )
- s_buff_1 = s_buff_1 + CHR(26)
- ENDIF
-
- * 2. write modified buffer 1 recs
- nul = FWRITE( n_SDF_hand, s_buff_1 )
-
- * 3. get new b1 end
- a_B1_end = FSEEK( n_SDF_hand, 0, 1)
-
-
- * 4. move b2 --> b1
- s_buff_1 = s_buff_2
-
- IF LEN(s_buff_2) = 0
- EXIT
- ENDIF
-
- * 5. goto old b2 end
- nul = FSEEK( n_SDF_hand, a_B2_end, 0)
-
- * 6. read new b2 SDF recs
- s_buff_2 = FREAD(n_SDF_hand, a_buff_size)
-
- * 7. get new b2 end
- a_b2_end = FSEEK(n_SDF_hand, 0, 1)
-
- * 8. convert new b2 to DBF recs
- **= this translates all CR/LF's into " " in the 64k string variable
- s_buff_2 = STRTRAN( s_buff_2, m_EOR_mark, " ")
-
-
- ENDDO
-
-
- WAIT WINDOW NOWAIT ;
- [ 100% DONE ]
-
- RETURN .T.
-
- ****************************************************************************
- *
- *
- * FUNCTION dec2hex
- *
- *
- ***************************************************************************
- FUNCTION dec2hex
- PARAMETERS m_number
-
- m_temp = 0
- DECLARE array[4]
- array = 0 && initializes array elements as zeros
- array[1] = INT(m_number / 2^24)
- m_temp = MOD(m_number, 2^24)
- array[2] = INT(m_temp / 2^16)
- m_temp = MOD(m_temp, 2^16)
- array[3] = INT(m_temp / 2^8)
- array[4] = MOD(m_temp, 2^8)
-
- RETURN CHR(array[4]) + CHR(array[3]) + CHR(array[2]) + CHR(array[1])
- ******************************************************************
- *
- *
- * FUNCTION all_ok
- *
- *
- *
- *
- ******************************************************************
- FUNCTION all_ok
-
- IF !FILE(s_sdf_file)
- ?? CHR(7)
- ?? CHR(7)
- WAIT WINDOW [cant find the ascii SDF file you specified: ] + s_sdf_file
- RETURN .F.
- ENDIF
-
- IF FILE(s_template_file)
- IF USED('template')
- USE IN template
- ENDIF
- IF USED(STRTRAN(s_template_file,".DBF",""))
- USE IN (STRTRAN(s_template_file,".DBF",""))
- ENDIF
- ELSE
- ?? CHR(7)
- ?? CHR(7)
- WAIT WINDOW [ CAN'T FIND THE TEMPLATE FILE YOU SPECIFIED: ] + m_header_file
- RETURN .F.
- ENDIF
-
- RETURN .T.
-
-
- ******************************************************************
- *
- * FUNCTION get_template
- *
- ******************************************************************
- FUNCTION get_template
- PARAMETERS n_rec_size, n_head_size, n_f_hand, s_head_str
- *==============================================================
- * 1. get size of record & size of header in normal FP method
- *==============================================================
- *--make sure the template file ain't open
- *--get rid of path if it was included in parmater
- m_header_dbf = STRTRAN( ALLTRIM( SUBSTR( s_template_file, ;
- RAT("\", s_template_file)+1)), ".DBF", "")
- IF USED(m_header_dbf)
- USE IN (m_header_dbf)
- ENDIF
- SELE 0
- USE (s_template_file) ALIAS template EXCLUSIVE
- n_rec_size = RECSIZE() && find out preferred record size
- n_head_size = HEADER() && find out size of header
- USE IN template
-
-
- *==============================================================
- * 2. Low-level store to var the header of template .DBF
- *==============================================================
- *---LOW LEVEL OPEN the template file & get literal DBF header
- n_f_hand = FOPEN( s_template_file)
- s_head_str = FREAD( n_f_hand, n_head_size )
- nul = FCLOSE( n_f_hand ) && n_f_hand is the file handle
-
-
- *==============================================================
- *
- * FUNCTION get_sdf
- *
- *==============================================================
- FUNCTION get_sdf
- PARAMETERS n_SDF_Hand, a_SDF_size, a_Rec_size, g_rec_size, m_EOR1, m_EOR2, m_EOR_mark
-
- *==============================================================
- *
- * ASCII SDF file section:: getting true recsize & file size
- * AND getting record termination method,
- * i.e. CR/LF or just CR or just LF
- *
- *==============================================================
- *--open the ASCII SDF DATA file
- n_SDF_hand = FOPEN( s_sdf_file, 2)
- *--size of whole SDF file
- a_SDF_size = FSEEK(n_SDF_hand, 0, 2)
- *--go back to the beginning of file
- = FSEEK(n_SDF_hand,0)
- *---get actual physical size of SDF records WITH CR/LF
- g_rec_size = LEN( FGETS( n_SDF_hand, n_rec_size*2 ))
-
- *--get EOR marker method: both CR/LF or one or just CR or LF ?
- = FSEEK( n_SDF_hand, g_rec_size, 0)
- m_EOR1 = FREAD( n_SDF_hand, 1)
- m_EOR2 = FREAD( n_SDF_hand, 1)
- IF ASC(m_EOR1) = 13 OR ASC(m_EOR1) = 10
- m_EOR_mark = m_EOR1
- ENDIF
- IF ASC(m_EOR2) = 13 OR ASC(m_EOR2) = 10
- m_EOR_mark = m_EOR1 + m_EOR2
- ENDIF
- *--now we know the true look of the SDF record
- a_rec_size = g_rec_size + LEN(m_EOR_mark)
- *--go back to the beginning of file
- nul = FSEEK(n_SDF_hand,0)
- *==============================================================
- * end of SDF rec size & file size section
- *==============================================================
-
-
- *==============================================================
- *
- * FUNCTION error_traps
- * ERROR TRAPS BEFORE GOING ON
- *
- *==============================================================
- *==============================================================
- FUNCTION error_traps
- PARAMETERS a_N_recs_expected
- *==============================================================
- *--error trap for mis-matched header & SDF file
- *==============================================================
- IF n_rec_size # a_rec_size - LEN(m_EOR_mark) + 1
- WAIT WINDOW [file formats incompatible! DBF record IS ] ;
- + ALLTRIM(STR(n_rec_size)) + [ in length; expected ] + ;
- ALLTRIM(STR(a_rec_size+1)) + [!]
- =FCLOSE(n_SDF_hand)
- RETURN .F.
- ENDIF
- *==============================================================
- *==============================================================
- *---do some accounting:
- *==============================================================
- a_N_recs_expected = (a_SDF_size-1) / a_rec_size
- IF a_SDF_size % a_rec_size # 1 && one byte left over means the EOF ^Z
- WAIT WINDOW [ error! expected rec. count doesn't jibe with file size! ]
- =FCLOSE(n_SDF_hand)
- RETURN .F.
- ENDIF
- *==============================================================
- RETURN .T.
-
- *==============================================================
- *
- * FUNCTION get_buff_size
- *
- *==============================================================
- FUNCTION get_buff_size
- PARAMETERS a_buff_size, a_buff_recs
- *==============================================================
- * now, we must keep 2 buffers because of the header offset caused by
- * initially overwriting records with the header. so on the first loop
- * we grab the first n records buffer & write the header.
- * on every loop thereafter, we save the 2nd rec buffer that will be overwritten
- * by the first rec buffer, then write the 1st rec buffer (while converting the
- * records on the fly)
- *==============================================================
- *--instead of going record-by-record, we pull up as many rec's
- *--as we can; calculate max buffer size
- a_buff_size = FLOOR((n_buff_bytes / a_rec_size)) * a_rec_size
- *--how many recs per buffer?
- a_buff_recs = a_buff_size / a_rec_size
- *==============================================================
- * note: in FP 2.0, 64k was the max var size. In FP 2.5 (extended?)
- * the max var size apparently is up to 4 Meg. (!!). I've left this
- * buffer size at 64k.
- *
- *==============================================================
-
- *------------------------------------------------------------------
- *
- * FUNCTION chk_sdf
- *
- *-------------------------------------------------------------------
- FUNCTION chk_sdf
- PARAMETERS n_SDF_Hand, a_SDF_size, a_Rec_size, g_rec_size, m_EOR_mark
- PRIVATE nInitLen, is_good_sdf, n_counter
-
- nul = FSEEK(n_SDF_hand,0) && go top
- nInitLen = LEN( FGETS( n_SDF_hand ) ) && get length of first record
- n_counter = 0
-
- is_good_sdf = .T.
-
- DO WHILE .T.
- sStr = FGETS( n_SDF_hand )
- IF EMPTY(sStr) && end of file
- EXIT
- ENDIF
- IF LEN( sStr ) # nInitLen && we found a record of incorrect length
- is_good_sdf = .F.
- EXIT
- ENDIF
-
- n_counter = n_counter + 1
- *--display on screen amount completed
- IF MOD(n_counter, 100) = 0
- WAIT WINDOW NOWAIT ;
- "VALIDATING ALL RECORD LENGTHS IN SDF FILE. " + ;
- STR( ( nInitLen * n_Counter / a_SDF_size * 100), 5,2) + [ % DONE ]
- ENDIF
-
-
- ENDDO
-
- nul = FSEEK(n_SDF_hand,0) && go top
-
- RETURN is_good_sdf
-
-
- *==============================================================
- *
- * FUNCTION write_header
- *
- *==============================================================
- FUNCTION write_header
- PARAMETERS s_buff_1, s_buff_2, a_b2_end, a_B1_end, a_EOH_posit
- *--set it up for the header write
-
- *--init buffer 1 :: get SDF records
- s_buff_1 = FREAD(n_SDF_hand, a_buff_size)
- s_buff_1 = STRTRAN( s_buff_1, m_EOR_mark, " ")
-
- *--get BUFFER 2 SDF records
- s_buff_2 = FREAD(n_SDF_hand, a_buff_size)
- s_buff_2 = STRTRAN( s_buff_2, m_EOR_mark, " ") && this translates all CR/LF's into " " in the 64k string variable
- a_b2_end = FSEEK(n_SDF_hand, 0, 1)
-
- *--BOF
- nul = FSEEK( n_SDF_hand , 0)
-
- *--write the header!
- nul = FWRITE( n_SDF_hand, s_head_str )
-
- *--!! CRITICAL !! ONLY ONCE!
- *--!! write a space for the 1st record's delete field
- nul = FWRITE( n_SDF_hand, " ")
-
- *--this is the end of header posit
- a_EOH_posit = FSEEK( n_SDF_hand, 0, 1 )
- a_B1_end = FSEEK( n_SDF_hand, 0, 1 )
-
- WAIT WINDOW NOWAIT ;
- STR( (a_b1_end / a_SDF_size * 100), 5,2) + [ % DONE ]
-
- *======================================================
- *
- * END OF 1st time SECTION
- *
- *======================================================
-
-
- RETURN
- *======================================================================
- *
- * FUNCTION adjust_fsize
- *
- *======================================================================
- FUNCTION adjust_fsize
- *======================================================================
- *======================================================================
- *===adjust file size
- *======================================================================
- *======================================================================
-
- n_file_size = n_head_size + (n_rec_size * a_N_recs_expected) + 1 && plus byte @ EOF()
- nul = FCHSIZE( n_SDF_hand, n_file_size )
-
- *--go to BOF + 4 in new DBF-header AND write # of records
- nul = FSEEK( n_SDF_hand, 4, 0 )
- *--write the # of records
- nul = FWRITE( n_SDF_hand, Dec2Hex( a_N_recs_expected ) )
- nul = FFLUSH( n_SDF_hand )
- nul = FCLOSE(n_SDF_hand)
- *======================================================================
- *======================================================================
- *======================================================================
-
- WAIT CLEAR
- CLOSE ALL
- CLEAR ALL
- RELEASE ALL
- FLUSH
-
-
- RETURN
-