Don't understand objects
I thought I had a clever idea for reading a fixed-format text file, or more specifically, TWO such files at the same time, so I could compare them. I thought I would make an object! that would define a fixed-format file and some functions on it. The functions would allow me to specify field names for the 'fields' on each line, with positions and lengths. Then I could use those specified names as words and refer to the fields by name. Two sample files look like this: FILE1: STEVEN 01-MAR-1951 MR. SMITH 02-APR-1952 FILE2: WILLIAM 01-FEB-1953 MR. JOHNSON 02-MAY-1954 The name starts in position 1 for length 20; the DOB in position 21 for length 11. In the script below, I define a Fixed-Format File (FFF) object, and then define two objects based on it, FILE1 and FILE2. When I define FILE1 or FILE2, I want to specify that positions 1-20 will be referred to as NAME, and 21-32 by DOB. I pass in the words NAME and DOB, and when I 'read' a 'record,' I 'set' NAME and DOB to substrings extracted out of the data based on the specified positions and lengths. The above scheme all works fine when I am dealing with only one instance of FFF, but if I try to make TWO, only the NAME and DOB words from the most-recently defined instance are available. As indicated in the comments, I can't refer to FILE1/NAME or FILE2/NAME, but only NAME, which gets me the value from the instance most recently created. What am I not understanding? The script is below, followed by the results of running it. Sorry for the length. It really is only two operations. The 'open' function reads the file and defines the 'fields' expected and where they are (by position and length). The 'read' function gets the next line of text and sets the 'field names' to values pulled out of the text line. Thank you. R E B O L [ Title: 'Fixed-Format File object' ] FFF: make object! [ FILE-ID: none ;; file name passed to 'open' function FIELDS: none ;; [fieldname locationpair fieldname locationpair, etc] FILE-DATA: [] ;; whole file in memory, as block of lines RECORD-AREA: '' ;; one line from FILE-DATA, for picking apart RECORD-NUMBER: 0 ;; for keeping track of which line we picked FILE-SIZE: 0 ;; number of lines in FILE-DATA EOF: false ;; set when we 'pick' past end ;; -------------------------- OPEN-INPUT: func [ FILEID [file!] ;; will be a file name FIELDLIST [block!] ;; will be sets of word! and pair! ] [ ;; -- Save what was passed to us. FILE-ID: FILEID FIELDS: copy [] FIELDS: copy FIELDLIST ;; -- Read the entire file into memory and set various items in preparation ;; -- for reading the file a record at a time. FILE-DATA: copy [] FILE-DATA: read/lines FILE-ID FILE-SIZE: length? FILE-DATA RECORD-NUMBER: 0 EOF: false ] ;; -------------------------- READ-RECORD: does [ ;; pick a line if there are lines left to be picked RECORD-NUMBER: RECORD-NUMBER + 1 if (RECORD-NUMBER > FILE-SIZE) [ EOF: true return EOF ] RECORD-AREA: copy '' RECORD-AREA: copy pick FILE-DATA RECORD-NUMBER ;; set the words passed to the 'open' function to values extracted ;; out of the data, based on the locations passed to the 'open' function foreach [FIELDNAME POSITION] FIELDS [ RECORD-AREA: head RECORD-AREA RECORD-AREA: skip RECORD-AREA (POSITION/x - 1) set FIELDNAME copy/part RECORD-AREA POSITION/y ] ] ] ;; Now test the object by making two instances of it. FILE1: make FFF [] FILE1/OPEN-INPUT %rtest1.txt [NAME 1X20 DOB 21X11] FILE1/READ-RECORD ;; can't say FILE1/NAME or FILE1/DOB; must use just NAME and DOB print [NAME ' ' DOB] FILE1/READ-RECORD print [NAME ' ' DOB] FILE1/READ-RECORD probe FILE1/EOF print '-------------------------' FILE2: make FFF [] FILE2/OPEN-INPUT %rtest2.txt [NAME 1X20 DOB 21X11] FILE2/READ-RECORD ;; can't say FILE1/NAME or FILE1/DOB; must use just NAME and DOB print [NAME ' ' DOB] FILE2/READ-RECORD print [NAME ' ' DOB] FILE2/READ-RECORD probe FILE2/EOF print '-------------------------' ;; If we try to refer to a NAME or DOB in FILE1, we crash: print FILE1/NAME halt Results: STEVEN 01-MAR-1951 MR. SMITH 02-APR-1952 true ------------------------- WILLIAM 01-FEB-1953 MR. JOHNSON 02-MAY-1954 true ------------------------- ** Script Error: Invalid path value: NAME ** Near: print FILE1/NAME halt >>
posted by: Steven White 28-Dec-2015/17:18:51-8:00
Try something like this.....The code creates an object, so you can do stuff like: probe file1/record make object! [ NAME: "STEVEN " DOB: "01-MAR-1951" ] The magic is in the line: record: make record compose [(to-set-word fieldname) copy/part RECORD-AREA POSITION/y] Full code: R E B O L [ Title: 'Fixed-Format File object' ] FFF: make object! [ FILE-ID: none ;; file name passed to 'open' function FIELDS: none ;; [fieldname locationpair fieldname locationpair, etc] FILE-DATA: [] ;; whole file in memory, as block of lines RECORD-AREA: "" ;; one line from FILE-DATA, for picking apart RECORD: none ;; Current record RECORD-NUMBER: 0 ;; for keeping track of which line we picked FILE-SIZE: 0 ;; number of lines in FILE-DATA EOF: false ;; set when we 'pick' past end ;; -------------------------- OPEN-INPUT: func [ FILEID [file!] ;; will be a file name FIELDLIST [block!] ;; will be sets of word! and pair! ] [ ;; -- Save what was passed to us. FILE-ID: FILEID FIELDS: copy [] FIELDS: copy FIELDLIST ;; -- Read the entire file into memory and set various items in preparation ;; -- for reading the file a record at a time. FILE-DATA: copy [] FILE-DATA: read/lines FILE-ID FILE-SIZE: length? FILE-DATA RECORD-NUMBER: 0 EOF: false ] ;; -------------------------- READ-RECORD: does [ ;; pick a line if there are lines left to be picked RECORD-NUMBER: RECORD-NUMBER + 1 if (RECORD-NUMBER > FILE-SIZE) [ EOF: true return EOF ] RECORD-AREA: copy "" RECORD-AREA: copy pick FILE-DATA RECORD-NUMBER ;; set the words passed to the 'open' function to values extracted ;; out of the data, based on the locations passed to the 'open' function record: make object! [] foreach [FIELDNAME POSITION] FIELDS [ RECORD-AREA: head RECORD-AREA RECORD-AREA: skip RECORD-AREA (POSITION/x - 1) record: make record compose [(to-set-word fieldname) copy/part RECORD-AREA POSITION/y] ] ] ]
posted by: Sunanda 28-Dec-2015/21:00:18-8:00
|