home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / SDF2DBF.ZIP / SDF2DBF.PRG
Encoding:
Text File  |  1995-03-10  |  16.5 KB  |  502 lines

  1. ********************************************************************************
  2. *  PROC sdf2dbf (FOR FOXPRO)  THE FAST VERSION
  3. *
  4. *  SYNTAX:
  5. *  DO sdf2dbf WITH ;
  6. *   [<expC>], ;          && dbf header template
  7. *   [<expC>], ;          && sdf ascii file to be converted to dbf format
  8. *   [<expN>]             && buffer size; allows between 64k & 256k buffer size
  9. *
  10. *  PURPOSE: Converts IN-PLACE Standard Data Format (SDF) files TO .DBF file
  11.  
  12. *      This is great for those giant ascii files you download from your mainframe that 
  13. *      are too big to do an 'APPEND FROM' into a receiving .DBF file. sd2dbf.prg 
  14. *      performs in-place conversion of an SDF fixed-length ascii file to .DBF format. 
  15. *      All you need is a .DBF file with zero records as the header template file, and the 
  16. *      SDF file to be converted in-place. You may specify the dual buffer size from 
  17. *      64k to 256k as a 3rd parameter, but I recommend sticking with 64k size buffers. 
  18. *      It verifies that the SDF table has no variable length records before continuing. 
  19. *      This is still a beta version, so not all the error traps are there....you've 
  20. *      been warned (i.e. make sure you have a few more spare bytes of disk lying around
  21. *      in case the converted file has to grow a little)
  22.  
  23. *
  24. *  DANGER, WILL ROBINSON!
  25. *  WARNING: The records in the SDF file *MUST* be FIXED LENGTH AND *MUST*
  26. *           have and End-of-record marker like CR/LF or CR or LF. If the rec's
  27. *           are variable length, use the SDF2DBF.PRG listed in the 
  28. *           DECEMBER '92 DataBased Advisor.  
  29. *           ALSO: if you think there may be CR's or LF's any where else 
  30. *           in the SDF file, DON'T DO THIS!  
  31. *
  32. *
  33. *  ADVANTAGE: If your SDF data is 100% FIXED LENGTH, this version of
  34. *         SDF2DBF.PRG will run faster and doesn't require ADDITIONAL 
  35. *         DISK SPACE for work areas or exception processing.  In lieu
  36. *         of the record-by-record approach seen in Steve Freides DBA 
  37. *         SDF2DBF version, this one gobbles up the SDF rec's in 64 k chunks, 
  38. *         does a STRTRAN( big_ole_data_buffer, CHR(13)+CHR(10), " ")
  39. *         to change the  CR/LF's into the deletion field, 
  40. *         and keeps juggling both 64k buffers until it's done.  (the
  41. *         2 data buffers are required becaused of the displacement caused
  42. *         by introducing the DBF header to the top of the file)
  43.  
  44. *      Enjoy. -leebert
  45. *
  46. *       COPYRIGHT: Released into public domain.         
  47. *
  48. *       Author: Lee Rodgers
  49. *       leebert@io.com
  50. *       73144.2276@CompuServe.com
  51. *
  52. *
  53. ********************************************************************************
  54. *FUNCTION sdf2dbf
  55. PARAMETERS s_template_file, s_sdf_file, n_buff_bytes
  56.  
  57. IF PARAMETERS() < 3 OR n_buff_bytes < 64000 OR n_buff_bytes > 256000
  58.   n_buff_bytes = 64000  && conservative FP2.0 setting
  59. ENDIF  
  60.  
  61.  
  62. IF PARAMETERS() < 2 OR EMPTY(s_template_file) OR EMPTY(s_sdf_file)
  63.    ?? CHR(7)  && BEEP!
  64.    ?? CHR(7)  && BEEP!  
  65.    WAIT WINDOW  [2 paramters are required!]
  66.    RETURN .F.
  67. ENDIF  
  68. s_template_file = UPPER(s_template_file )
  69. s_sdf_file      = UPPER(s_sdf_file)
  70.  
  71. IF !all_ok()
  72.   RETURN
  73. ENDIF
  74.  
  75. STORE '' TO s_head_str
  76. STORE 0 TO n_rec_size, n_head_size, n_f_hand
  77. =get_template( @n_rec_size, @n_head_size, @n_f_hand, @s_head_str )
  78.  
  79. STORE 0 TO n_SDF_hand, a_SDF_size, g_rec_size, a_rec_size
  80. STORE '' TO m_EOR1, m_EOR2, m_EOR_mark
  81. =get_sdf( @n_SDF_Hand, @a_SDF_size, @a_Rec_size, @g_rec_size, @m_EOR1, @m_EOR2, @m_EOR_mark )
  82.  
  83. STORE 0 TO a_N_recs_expected
  84. IF !error_traps( @a_N_recs_expected )
  85.   =FCLOSE( n_SDF_hand )
  86.   RETURN .F.  
  87. ENDIF
  88.  
  89. IF !chk_sdf( n_SDF_Hand, a_SDF_size, a_Rec_size, g_rec_size, m_EOR_mark )
  90.   WAIT WINDOW "There are variable length records in the SDF File."
  91.   RETURN .F.
  92. ENDIF  
  93.  
  94. STORE 0 TO a_buff_size, a_buff_recs
  95. =get_buff_size( @a_buff_size, @a_buff_recs )
  96.  
  97. =convert_loop()
  98.  
  99. =adjust_fsize()
  100.  
  101. RETURN
  102. *================================================================
  103. *
  104. *  FUNCTION convert_loop
  105. *
  106. *================================================================
  107. FUNCTION convert_loop
  108.  
  109. PRIVATE a_b1_end, n_counter, s_buff_1, s_buff_2, a_b2_end, a_b1_end, a_EOH_posit
  110.  
  111. WAIT CLEAR 
  112.  
  113. STORE '' TO s_buff_1, s_buff_2
  114. STORE 0 TO a_b2_end, a_B1_end, a_EOH_posit 
  115.  
  116. a_b1_end  = 0  && the file position marker for buffer # 1
  117. n_counter = 0  && today's show was brought to you by the numbers Σ n+1
  118.  
  119. DO WHILE .T. AND (1=1)  && i've actually seen someone seriously code this. " IF 1=1 "
  120.                         && question is: what happens when !(1 = 1) ?
  121.                         && a: reality as we know has ceased to exist!
  122.  
  123.   n_counter = n_counter + 1
  124.   
  125.   *--display on screen amount completed
  126.     WAIT WINDOW NOWAIT ;
  127.     STR( (a_b1_end / a_SDF_size * 100), 5,2) + [ % DONE ] 
  128.  
  129.   *============================================================
  130.   *   ok. 1st time through: need to write in header, but
  131.   *   first, load up both buffers, then write header
  132.   *============================================================
  133.   IF n_counter = 1  && first time through: 
  134.                     && write the header into the SDF file
  135.     =write_header(@s_buff_1, @s_buff_2, @a_b2_end, @a_B1_end, @a_EOH_posit )
  136.   ENDIF
  137.  
  138. * steps 
  139. * 1. goto old b1 (buffer 1) end
  140. * 2. write modified b1 (buffer 1) recs
  141. * 3. get new b1 end
  142. * 4. move b2 (buffer # 2) into b1 (buffer #1)
  143. * 5. goto old b2 end
  144. * 6. read new b2 SDF recs
  145. * 7. get new b2 end
  146. * 8. convert new b2 to DBF recs
  147.     
  148. * 1. goto old b1 end
  149.     nul =  FSEEK( n_SDF_hand, a_B1_end, 0)
  150.  
  151.     *--if we're on the last records, get rid of 
  152.     *--the extra delete field and change it to a ^Z
  153.     IF LEN(s_buff_2) = 0
  154.       s_buff_1 = SUBSTR( s_buff_1, 1, LEN(s_buff_1)-2 )
  155.       s_buff_1 = s_buff_1 + CHR(26)
  156.     ENDIF
  157.  
  158. * 2. write modified buffer 1 recs
  159.     nul =  FWRITE( n_SDF_hand, s_buff_1 )
  160.  
  161. * 3. get new b1 end
  162.     a_B1_end = FSEEK( n_SDF_hand, 0, 1)
  163.     
  164.  
  165. * 4. move b2 --> b1
  166.     s_buff_1 = s_buff_2
  167.  
  168.     IF LEN(s_buff_2) = 0
  169.       EXIT
  170.     ENDIF
  171.     
  172. * 5. goto old b2 end
  173.     nul =  FSEEK( n_SDF_hand, a_B2_end, 0)    
  174.  
  175. * 6. read new b2 SDF recs
  176.     s_buff_2 = FREAD(n_SDF_hand, a_buff_size)
  177.  
  178. * 7. get new b2 end
  179.     a_b2_end = FSEEK(n_SDF_hand, 0, 1)
  180.  
  181. * 8. convert new b2 to DBF recs
  182. **= this translates all CR/LF's into " " in the 64k string variable
  183.     s_buff_2 = STRTRAN( s_buff_2, m_EOR_mark, " ")
  184.  
  185.  
  186. ENDDO
  187.  
  188.  
  189. WAIT WINDOW NOWAIT ;
  190.  [ 100% DONE ] 
  191.  
  192. RETURN .T.
  193.  
  194. ****************************************************************************
  195. *
  196. *
  197. *                       FUNCTION dec2hex
  198. *
  199. *
  200. ***************************************************************************
  201. FUNCTION dec2hex
  202. PARAMETERS m_number
  203.  
  204. m_temp    = 0
  205. DECLARE array[4]
  206. array    = 0  && initializes array elements as zeros
  207. array[1] = INT(m_number / 2^24)
  208. m_temp   = MOD(m_number,  2^24)
  209. array[2] = INT(m_temp / 2^16)
  210. m_temp   = MOD(m_temp,  2^16) 
  211. array[3] = INT(m_temp /  2^8)
  212. array[4] = MOD(m_temp,   2^8)
  213.  
  214. RETURN CHR(array[4]) + CHR(array[3]) + CHR(array[2]) + CHR(array[1])
  215. ******************************************************************
  216. *
  217. *
  218. *               FUNCTION all_ok
  219. *
  220. *
  221. *
  222. *
  223. ******************************************************************
  224. FUNCTION all_ok
  225.  
  226. IF !FILE(s_sdf_file)
  227.    ?? CHR(7)
  228.    ?? CHR(7)
  229.    WAIT WINDOW [cant find the ascii SDF file you specified: ] + s_sdf_file
  230.    RETURN .F.
  231. ENDIF
  232.  
  233. IF FILE(s_template_file)
  234.    IF USED('template')
  235.      USE IN template
  236.    ENDIF
  237.    IF USED(STRTRAN(s_template_file,".DBF",""))
  238.      USE IN (STRTRAN(s_template_file,".DBF",""))
  239.    ENDIF
  240. ELSE
  241.    ?? CHR(7)
  242.    ?? CHR(7)    
  243.    WAIT WINDOW  [ CAN'T FIND THE TEMPLATE FILE YOU SPECIFIED: ] + m_header_file
  244.    RETURN .F.
  245. ENDIF
  246.  
  247. RETURN .T.
  248.  
  249.  
  250. ******************************************************************
  251. *
  252. *  FUNCTION get_template
  253. *
  254. ******************************************************************
  255. FUNCTION get_template
  256. PARAMETERS n_rec_size, n_head_size, n_f_hand, s_head_str
  257. *==============================================================
  258. *   1.  get size of record & size of header in normal FP method
  259. *==============================================================
  260. *--make sure the template file ain't open
  261. *--get rid of path if it was included in parmater
  262. m_header_dbf = STRTRAN( ALLTRIM( SUBSTR( s_template_file, ;
  263.                RAT("\", s_template_file)+1)), ".DBF", "")
  264. IF USED(m_header_dbf)
  265.   USE IN (m_header_dbf)
  266. ENDIF
  267. SELE 0
  268. USE (s_template_file) ALIAS template EXCLUSIVE
  269. n_rec_size  = RECSIZE()   && find out preferred record size
  270. n_head_size = HEADER()   && find out size of header
  271. USE IN template
  272.  
  273.  
  274. *==============================================================
  275. *  2. Low-level store to var the header of template .DBF
  276. *==============================================================
  277. *---LOW LEVEL OPEN the template file & get literal DBF header
  278. n_f_hand      = FOPEN(  s_template_file)
  279. s_head_str    = FREAD(  n_f_hand, n_head_size )
  280. nul           = FCLOSE( n_f_hand )   && n_f_hand is the file handle
  281.  
  282.  
  283. *==============================================================
  284. *
  285. *  FUNCTION get_sdf
  286. *
  287. *==============================================================
  288. FUNCTION get_sdf
  289. PARAMETERS n_SDF_Hand, a_SDF_size, a_Rec_size, g_rec_size, m_EOR1, m_EOR2, m_EOR_mark
  290.  
  291. *==============================================================
  292. *
  293. *  ASCII SDF file section:: getting true recsize & file size
  294. *                           AND getting record termination method,
  295. *                           i.e. CR/LF or just CR or just LF
  296. *
  297. *==============================================================
  298. *--open the ASCII SDF DATA file
  299. n_SDF_hand = FOPEN( s_sdf_file, 2)
  300. *--size of whole SDF file
  301. a_SDF_size = FSEEK(n_SDF_hand, 0, 2)
  302. *--go back to the beginning of file
  303. = FSEEK(n_SDF_hand,0)
  304. *---get actual physical size of SDF records WITH CR/LF
  305. g_rec_size = LEN( FGETS( n_SDF_hand, n_rec_size*2 ))
  306.  
  307. *--get EOR marker method: both CR/LF or one or just CR or LF ?
  308. = FSEEK( n_SDF_hand, g_rec_size, 0)
  309. m_EOR1 = FREAD( n_SDF_hand, 1)
  310. m_EOR2 = FREAD( n_SDF_hand, 1)
  311. IF ASC(m_EOR1) = 13 OR ASC(m_EOR1) = 10
  312.    m_EOR_mark = m_EOR1
  313. ENDIF
  314. IF ASC(m_EOR2) = 13 OR ASC(m_EOR2) = 10
  315.    m_EOR_mark = m_EOR1 + m_EOR2
  316. ENDIF
  317. *--now we know the true look of the SDF record
  318. a_rec_size = g_rec_size + LEN(m_EOR_mark)
  319. *--go back to the beginning of file
  320. nul =  FSEEK(n_SDF_hand,0)
  321. *==============================================================
  322. *  end of SDF rec size & file size section
  323. *==============================================================
  324.  
  325.  
  326. *==============================================================
  327. *
  328. * FUNCTION error_traps
  329. * ERROR TRAPS BEFORE GOING ON
  330. *
  331. *==============================================================
  332. *==============================================================
  333. FUNCTION error_traps
  334. PARAMETERS a_N_recs_expected
  335. *==============================================================
  336. *--error trap for mis-matched header & SDF file
  337. *==============================================================
  338. IF n_rec_size # a_rec_size - LEN(m_EOR_mark) + 1
  339.   WAIT WINDOW [file formats incompatible! DBF record IS ] ;
  340.            + ALLTRIM(STR(n_rec_size)) + [ in length; expected ] + ;
  341.            ALLTRIM(STR(a_rec_size+1)) + [!]
  342.   =FCLOSE(n_SDF_hand)             
  343.   RETURN .F.
  344. ENDIF               
  345. *==============================================================
  346. *==============================================================
  347. *---do some accounting:
  348. *==============================================================
  349. a_N_recs_expected = (a_SDF_size-1) / a_rec_size
  350. IF a_SDF_size % a_rec_size # 1 && one byte left over means the EOF ^Z
  351.   WAIT WINDOW [ error!  expected rec. count doesn't jibe with file size! ]
  352.   =FCLOSE(n_SDF_hand)             
  353.   RETURN .F.
  354. ENDIF
  355. *==============================================================
  356. RETURN .T.
  357.  
  358. *==============================================================
  359. *
  360. *  FUNCTION get_buff_size
  361. *
  362. *==============================================================
  363. FUNCTION get_buff_size
  364. PARAMETERS a_buff_size, a_buff_recs 
  365. *==============================================================
  366. *   now, we must keep 2 buffers because of the header offset caused by
  367. *   initially overwriting records with the header.  so on the first loop
  368. *   we grab the first n records buffer & write the header.
  369. *   on every loop thereafter, we save the 2nd rec buffer that will be overwritten 
  370. *   by the first rec buffer, then write the 1st rec buffer (while converting the
  371. *   records on the fly)
  372. *==============================================================
  373. *--instead of going record-by-record, we pull up as many rec's 
  374. *--as we can; calculate max buffer size
  375. a_buff_size = FLOOR((n_buff_bytes / a_rec_size)) * a_rec_size
  376. *--how many recs per buffer?
  377. a_buff_recs = a_buff_size / a_rec_size
  378. *==============================================================
  379. * note:  in FP 2.0, 64k was the max var size.  In FP 2.5 (extended?)
  380. * the max var size apparently is up to 4 Meg. (!!).  I've left this
  381. * buffer size at 64k.
  382. *
  383. *==============================================================
  384.  
  385. *------------------------------------------------------------------
  386. *
  387. *  FUNCTION chk_sdf
  388. *
  389. *-------------------------------------------------------------------
  390. FUNCTION chk_sdf
  391. PARAMETERS n_SDF_Hand, a_SDF_size, a_Rec_size, g_rec_size, m_EOR_mark
  392. PRIVATE nInitLen, is_good_sdf, n_counter
  393.  
  394. nul =  FSEEK(n_SDF_hand,0)  && go top
  395. nInitLen = LEN( FGETS( n_SDF_hand ) )  && get length of first record
  396. n_counter = 0
  397.  
  398. is_good_sdf = .T.
  399.  
  400. DO WHILE .T.
  401.   sStr = FGETS( n_SDF_hand )
  402.   IF EMPTY(sStr)  && end of file
  403.     EXIT
  404.   ENDIF
  405.   IF LEN( sStr ) # nInitLen  && we found a record of incorrect length 
  406.     is_good_sdf = .F.
  407.     EXIT
  408.   ENDIF
  409.   
  410.   n_counter = n_counter + 1
  411.   *--display on screen amount completed
  412.   IF MOD(n_counter, 100) = 0
  413.     WAIT WINDOW NOWAIT ;
  414.     "VALIDATING ALL RECORD LENGTHS IN SDF FILE.  " + ;
  415.     STR( ( nInitLen * n_Counter / a_SDF_size * 100), 5,2) + [ % DONE ] 
  416.   ENDIF
  417.  
  418.   
  419. ENDDO
  420.  
  421. nul =  FSEEK(n_SDF_hand,0)  && go top
  422.  
  423. RETURN is_good_sdf
  424.  
  425.  
  426. *==============================================================
  427. *
  428. *  FUNCTION write_header
  429. *
  430. *==============================================================
  431. FUNCTION write_header
  432. PARAMETERS s_buff_1, s_buff_2, a_b2_end, a_B1_end, a_EOH_posit
  433.     *--set it up for the header write
  434.  
  435.     *--init buffer 1 :: get SDF records
  436.     s_buff_1 = FREAD(n_SDF_hand, a_buff_size)
  437.     s_buff_1 = STRTRAN( s_buff_1, m_EOR_mark, " ")
  438.     
  439.     *--get BUFFER 2 SDF records
  440.     s_buff_2 = FREAD(n_SDF_hand, a_buff_size)
  441.     s_buff_2 = STRTRAN( s_buff_2, m_EOR_mark, " ")  && this translates all CR/LF's into " " in the 64k string variable
  442.     a_b2_end = FSEEK(n_SDF_hand, 0, 1)
  443.     
  444.     *--BOF
  445.     nul =  FSEEK( n_SDF_hand , 0)
  446.     
  447.     *--write the header!
  448.     nul =  FWRITE( n_SDF_hand, s_head_str )
  449.  
  450.     *--!! CRITICAL !! ONLY ONCE! 
  451.     *--!! write a space for the 1st record's delete field  
  452.     nul =  FWRITE( n_SDF_hand, " ")
  453.     
  454.     *--this is the end of header posit
  455.     a_EOH_posit = FSEEK( n_SDF_hand, 0, 1 )
  456.     a_B1_end    = FSEEK( n_SDF_hand, 0, 1 )
  457.  
  458.     WAIT WINDOW NOWAIT ;
  459.     STR( (a_b1_end / a_SDF_size * 100), 5,2) + [ % DONE ] 
  460.  
  461.   *======================================================
  462.   *
  463.   *  END OF 1st time SECTION
  464.   *
  465.   *======================================================
  466.  
  467.  
  468. RETURN
  469. *======================================================================
  470. *
  471. *  FUNCTION adjust_fsize
  472. *
  473. *======================================================================
  474. FUNCTION adjust_fsize
  475. *======================================================================
  476. *======================================================================
  477. *===adjust file size
  478. *======================================================================
  479. *======================================================================
  480.  
  481. n_file_size = n_head_size + (n_rec_size * a_N_recs_expected) + 1  && plus byte @ EOF()
  482. nul =  FCHSIZE( n_SDF_hand, n_file_size )
  483.  
  484. *--go to BOF + 4 in new DBF-header AND write # of records
  485. nul =  FSEEK( n_SDF_hand, 4, 0 )
  486. *--write the # of records 
  487. nul =  FWRITE( n_SDF_hand, Dec2Hex( a_N_recs_expected ) )
  488. nul =  FFLUSH( n_SDF_hand )
  489. nul =  FCLOSE(n_SDF_hand)             
  490. *======================================================================
  491. *======================================================================
  492. *======================================================================
  493.  
  494. WAIT CLEAR
  495. CLOSE ALL
  496. CLEAR ALL
  497. RELEASE ALL
  498. FLUSH
  499.  
  500.  
  501. RETURN
  502.