locln |
Table of contents
ProcedureLOCLN ( Locate lines in a text file ) SUBROUTINE LOCLN ( UNIT, BMARK, EMARK, LINE, BLINE, ELINE, FOUND ) AbstractLocate a group of lines in a text file delimited by markers. Required_ReadingNone. KeywordsFILES TEXT DeclarationsIMPLICIT NONE INTEGER UNIT CHARACTER*(*) BMARK CHARACTER*(*) EMARK CHARACTER*(*) LINE INTEGER BLINE INTEGER ELINE LOGICAL FOUND Brief_I/OVARIABLE I/O DESCRIPTION -------- --- -------------------------------------------------- UNIT I Logical unit connected to text file. BMARK I Begin marker. EMARK I End marker. LINE I-O Workspace. BLINE O Beginning line. ELINE O Ending line. FOUND O Markers found? Detailed_InputUNIT is a logical unit that has been connected to a text file by the calling program. Use the routine TXTOPR to open the file for read access and get its logical unit. The file pointer may be pointing to any line in the file due to previous read statements, for example, or due to previous calls to LOCLN. BMARK, EMARK are markers that delimit some group of lines in the part of the file following the current position of the file pointer. The group begins with the first line equivalent to BMARK and ends with the next line equivalent to EMARK, ignoring leading and trailing blanks. If BMARK is blank, the group of lines begins with the first line following the current position of the file pointer; if EMARK is blank, the group of lines ends with the last line in the file. LINE on input, is an arbitrary character string whose contents are ignored. LINE is used to read lines from the file connected to UNIT; its function is to determine the maximum length of the lines that can be read from the file. Lines longer than the declared length of LINE are truncated as they are read. Detailed_OutputLINE on output, is undefined. BLINE, ELINE are the line numbers of the first and last lines in the group delimited by BMARK and EMARK. By convention, the first line read by the routine is line 1; the second line is line 2; and so on. If BMARK is blank, BLINE will be 1. FOUND is .TRUE. if a group of lines delimited by BMARK and EMARK is found, and is .FALSE. otherwise. ELINE is the last line read by LOCLN, so if FOUND is .TRUE., the file pointer will be positioned on the line after ELINE. ParametersNone. Exceptions1) If FOUND is .FALSE., the values of BLINE and ELINE are not changed. 2) If an error occurs while reading from the input file, the error SPICE(FILEREADFAILED) is signaled. 3) Lines in the file that are longer than the declared length of LINE are truncated as they are read. If the truncation of line containing a marker causes truncation of that marker, it will not match the input value for that marker, so FOUND will be .FALSE. FilesSee argument UNIT. ParticularsThis routine locates delimited groups of lines in a text file. This allows files to be partitioned into sub-files; it also allows related inputs to be grouped together in a relatively free-format way. Examples1) Let FILE.TXT be a text file that contains the following lines. (The lines are numbered for reference, but these numbers do not appear in the file). 1 BEGIN POEM 2 Oh snail, 3 Climb Mount Fuji, 4 But slowly, slowly! 5 END POEM 6 7 BEGIN PROSE 8 Lady, one of us has this book open 9 to the wrong page. 10 END PROSE 11 12 BEGIN POEM 13 John Keats, John Keats, 14 John, 15 Put your scarf on. 16 END POEM 17 18 BEGIN QUOTE 19 That's not writing. That's typing. 20 21 (Truman Capote on Jack Kerouac) 22 END QUOTE 23 24 BEGIN POEM 25 Twice five syllables 26 Plus seven isn't much, but 27 That's haiku for you. 28 BEGIN POEM 29 30 BEGIN EQUATION 31 2 32 e = mc 33 END EQUATION Then the code fragment CALL TXTOPR ( 'FILE.TXT', UNIT ) BMARK = 'BEGIN POEM' EMARK = 'END POEM' CALL LOCLN ( UNIT, BMARK, EMARK, LINE, B, E, FOUND ) DO WHILE ( FOUND ) WRITE (*,*) 'Found poem between lines ', B, ' and ', E CALL LOCLN ( UNIT, BMARK, EMARK, LINE, B, E, FOUND ) END DO produces the following report: Found poem between lines 1 and 5 Found poem between lines 7 and 11 Found poem between lines 8 and 12 Note that line numbers are returned relative to the position of the file pointer when LOCLN is called. The following code fragment generates the numbers relative to the start of the file. REWIND ( UNIT ) OFFSET = 0 CALL LOCLN ( UNIT, BMARK, EMARK, LINE, B, E, FOUND ) DO WHILE ( FOUND ) WRITE (*,*) 'Found poem between lines ', . OFFSET + B, . ' and ', . OFFSET + E OFFSET = OFFSET + E CALL LOCLN ( UNIT, BMARK, EMARK, LINE, B, E, FOUND ) END DO CLOSE ( UNIT ) The following report is produced: Found poem between lines 1 and 5 Found poem between lines 12 and 16 Found poem between lines 24 and 28 2) Given the same file, the code fragment CALL TXTOPR ( 'FILE.TXT', UNIT ) CALL LOCLN ( UNIT, . 'begin poem', . 'end poem', . LINE, . B, . E, . FOUND ) CLOSE ( UNIT ) finds nothing because case is significant: FOUND is false, and B and E are unchanged. 3) This code fragment CALL TXTOPR ( 'FILE.TXT', UNIT ) CALL LOCLN ( UNIT, . ' ', . 'BEGIN PROSE', . LINE, . B, . E, . FOUND ) CLOSE ( UNIT ) when executed on the same file returns B = 1 and E = 7. In effect, a blank begin marker "matches" the first line that is read. Similarly, a blank end marker "matches" the last line of the file, the code fragment CALL TXTOPR ( 'FILE.TXT', UNIT ) CALL LOCLN ( UNIT, . 'BEGIN QUOTE', . ' ', . LINE, . B, . E, . FOUND ) CLOSE ( UNIT ) when executed on the same file returns B = 18 and E = 33. If both markers are blank, LOCLN basically counts the lines in the file. 4) The code fragment CALL TXTOPR ( 'FILE.TXT', UNIT ) MARK = 'BEGIN POEM' CALL LOCLN ( UNIT, MARK, MARK, LINE, FIRST, SECOND, FOUND ) CLOSE ( UNIT ) returns FIRST = 1 and SECOND = 12 -- the first two lines that are equivalent to MARK. 5) Nesting is not supported. That is, if UNIT is connected to a file containing the following lines (ignoring line numbers), 1 Begin Object 2 Begin Object 3 Begin Object 4 Just kidding! 5 End Object 6 End Object 7 End Object REWIND ( UNIT ) CALL LOCLN ( UNIT, . 'Begin Object' . 'End Object', . LINE, . B, . E, . FOUND ) returns B = 1 and E = 5, not E = 7. 6) Let UNIT be connected to a text file containing the following lines, again ignoring line numbers which are listed for easy reference. 1 The first case tests the capability of ... 2 3 NEW CASE 4 TARGET = JUPITER 5 EPOCH = 21 JUN 1992 13:04 6 END CASE 7 8 The next case uses a different target and a slightly 9 longer exposure time... 10 11 NEW CASE 12 TARGET = IO 13 EPOCH = 21 JUN 1992 13:04 14 EXPOSURE = 2.44 SECONDS 15 END CASE 16 17 The next case changes targets in order to... 18 19 NEW CASE 20 TARGET = EUROPA 21 EPOCH = 21 JUN 1992 13:04 22 EXPOSURE = 2.44 SECONDS 23 END CASE Then the code fragment REWIND ( UNIT ) BMARK = 'NEW CASE' EMARK = 'END CASE' CASES = 0 OFFSET = 0 CALL LOCLN ( UNIT, BMARK, EMARK, LINE, B, E, FOUND ) DO WHILE ( FOUND ) CASES = CASES + 1 BEG(CASES) = OFFSET + B END(CASES) = OFFSET + E OFFSET = OFFSET + E CALL LOCLN ( UNIT, BMARK, EMARK, LINE, B, E, FOUND ) END DO saves the locations of the various input cases (skipping past the intervening commentary) in the arrays BEG and END. After running the code, CASES, BEG, and END have the following values: CASES = 3 BEG = 3, 11, 19 END = 6, 15, 23 The following code fragment retrieves the i'th case. REWIND ( UNIT ) DO J = 1, BEG(I) - 1 READ (UNIT,FMT='(A)') LINE END DO DO J = BEG(I), END(I) READ (UNIT,FMT='(A)') LINE . . Process the line . END DO While this isn't an incredibly efficient way to process large files, it can be effective for smaller files. RestrictionsNone. Literature_ReferencesNone. Author_and_InstitutionJ. Diaz del Rio (ODC Space) J.E. McLean (JPL) W.L. Taber (JPL) VersionSPICELIB Version 1.1.0, 12-AUG-2021 (JDR) Added IMPLICIT NONE statement. Edited the header to comply with NAIF standard. SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) Comment section for permuted index source lines was added following the header. SPICELIB Version 1.0.0, 05-APR-1991 (JEM) |
Fri Dec 31 18:36:32 2021