Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

File pointer or pointer positioning

Status
Not open for further replies.

Volkmaniac

Technical User
Mar 19, 2003
104
US
Knob showed me a way I could count occurrences of an item within a text file:

fopen 1 fname read text
While not feof 1
fgets 01 sLine
If strncmp sLine "CCXXXX" 6
A++
else
If strncmp sLine "CCXXA" 5
B++
else
If strncmp sLine "CCXB" 4
C++
else

Now I'd like to take things a step further. Is there a way I can conduct the same type of search but only on specific columns within a file? For instance, let's say I have a file layout that tells me that a two digit code is in position 220-221 of each record in a file. Is there a way I can tell the script to only search those specific positions?
 
Probably the easiest way to do this is to use the substr command to copy the two-digit code to a temporary variable, then perform your comparison on just that data.


aspect@aspectscripting.com
 
That's not going to work. I have up to 1,000 columns and the string can only read 256. I can't extract the first 256 because I'd have to fgets 1 sLine first.
 
How are you getting the information from the file now, or are you? The only way I can see it working is if you continually issue fgets commands until you have the full line in multiple strings, then use the substr command to get the two digits out of the correct portion of the correct string.


aspect@aspectscripting.com
 
How can I do that? Is there a way I can fget the first 256 characters in a line? Would the syntax use multiple strings like this:

fopen 1 fname read text While not feof 1
fgets 01 sLine sLine2 sLine3 sLine4

I hope this works. I already know the positions I need so this would make things easy. I'll give it a try.
 
It worked. That's a great string utility

proc main
string sTest,Output ; String to contain message.
string sLine,sLine2,sLine3,sLine4,sLine5 ; String to contain message code.

Integer A = 0
Integer B = 0
Integer C = 0
Integer D = 0
Integer E = 0



fopen 1 "S:\Client Services\0930\rec\RFIIAR2I" read text
While not feof 1
fgets 01 sLine
fgets 01 sLine2
fgets 01 sLine3
fgets 01 sLine4
fgets 01 sLine5
substr sTest sLine 235 2
If strncmp sTest "05" 2
A++
else
If strncmp sTest "02" 2
B++
else
If strncmp sTest "03" 2
C++
else
If strncmp sTest "07" 2
D++
Endif
Endif
Endif
Endif
Endwhile
fclose 1 ; code, maybe encased in brackets.
; "[123] Message", for example.


clear
capture on

Termwrites "DPV Result Code"
Termwrites "`n`r"
Termwrites "`n`r"
strfmt Output "05 : %d" A
Termwrites Output
Termwrites "`n`r"
strfmt Output "02 : %d" B
Termwrites Output
Termwrites "`n`r"
strfmt Output "03 : %d" C
Termwrites Output
Termwrites "`n`r"
strfmt Output "07 : %d" D
Termwrites Output
Termwrites "`n`r"





endproc


 
Actually it didn't work. I found out it was doing exactly what you said. It's repositioning the pointer every 256 characters. The information I need is within the first 256 characters. Is there a way I can reposition the pointer to the beginning of the line at every line so it only grabs the first 256 characters in the string?

fopen 1 "S:\Client Services\1001\rec\RFXXX2I" readwrite text ;open the file for read

While not feof 1
fseek 1 0 0 (This is bringing back to the start of the file)
fgets 01 sLine1
ftell 1 FilePos ; Get position of pointer within file.
statmsg "File position = %ld" FilePos
substr sDpv sLine1 235 2
If strnicmp sDpv "01" 2
A++
else
If strnicmp sDpv "02" 2
B++
else
If strnicmp sDpv "03" 2
C++
Endif
Endif
Endif
Endwhile
fclose 1

strfmt Output "01 : %d" A
Termwrites Output
Termwrites "`n`r"
strfmt Output "02 : %d" B
Termwrites Output
Termwrites "`n`r"
strfmt Output "03 : %d" C
Termwrites Output



 
Shouldn't this work?

While not feof 1
fgets 1 sLine1
fseek 1 256 0
fputc 1 ','
strtok DataString sLine1 "," 1 ; Get first item from data list.
fgets 1 DataString
substr sDpv DataString 235 2
If strnicmp sDpv "01" 2
A++
else
 
OK. I'm trying a simpler approach. This is reading the correct position but sLine is not looping


fopen 1 "S:\Client Services\1001\rec\RFIIXXX" read text
While not feof 1

fgets 01 sLine
fseek 1 235 0
substr sDpv sLine 0 2
statmsg "%s" sDpv
If strnicmp sDpv "01" 2
A++
else
 
If I'm understanding the script correctly, you'll want to change the last argument of the fseek command from 0 to 1 so that the seek operation takes place from the current location (the end of the string you read from the file) rather than the beginning of the file (what 0 as the argument does).


aspect@aspectscripting.com
 
I quess I never understood how the file positioning works:

fseek 1 235 1

The first number is the file indicator

The second number is the position (like a column)

The third number is the start?

Would this be expected to take a long time? I've been running it for about 5 minutes and it still hasn't finished. I originally tried placing a comma at that position so I could parse it with strtok but it only placed a comma on the first line.
 
I tried changing it to 1 and it's still not working. It was just running for about 30 minutes when I shut it off.

fopen 1 "S:\Client Services\1001\rec\RFIIXXX" read text
While not feof 1

fgets 01 sLine
fseek 1 235 1
substr sDpv sLine 0 2
If strnicmp sDpv "01" 2
A++
else
 
The second number isn't truly a column, it's just the offset into the file, from the current position of the file pointer (when the last argument is zero). Everything looks OK to me, but I haven't tested the script yet (getting ready to head out for lunch). I'll look into it more later. You might want to get rid of the fgets command, use fseek to get you to the correct location (you'll want to use one fseek before the while loop to get to the right offset, then a second fseek in the while loop to "scroll down" through the records), then use fread to get just the two bytes you want from the file. My guess is that the end of the file is being reached, but the script is not recognizing that for some reason.


aspect@aspectscripting.com
 
You were right, it doesn't know the eof. I tried this and it ran to no end. I'm not sure if using a "1" at the end of fseek worked. The file position looked as if it was scrolling continuosly through the entire file. I only need positions 235 and 236. I'm not sure how I can use the second fseek to "scroll" to the next line.

fopen 1 "S:\Client Services\1001\rec\RFXX2I" read
fseek 1 235 0
While not feof 1
fread 1 sDpv 2 Len
If strnicmp sDpv "01" 2
A++
else
If strnicmp sDpv "02" 2
B++
else
If strnicmp sDpv "03" 2
C++
Endif
Endif
Endif
fseek 1 235 1
ftell 1 FilePos
statmsg "File position = %ld" FilePos
Endwhile
fclose 1
 
Here's something I came up with that should work (you'll need to modify it for the particular file you are working with). Here's the sample file I was working with:

aaaaaaa11aaaaaaaaaaaaa
bbbbbbb22bbbbbbbbbbbbb
ccccccc33ccccccccccccc
dddddcc44ccccccccccccc

And here's the script:

proc main
string sVar

fopen 0 "test.txt" READ
fseek 0 7 0
while not feof 0
fread 0 sVar 2
if nullstr sVar
exitwhile
endif
fseek 0 22 1
endwhile
fclose 0
endproc

The script opens the file (id 0), seeks into the file so that the next two bytes are the characters I'm trying to get (11). I read those two characters with fread, check to see if the result is null (more on that later). If not, the fseek command in the while loop moves enough characters into the file so that it is just before the next characters I want to get (22). You'll need to allocate two extra bytes in this fseek for the carriage return and line feed at the end of the current line.

Since it appears that EOF and ferror don't occur when you try to fseek past the end of the file, I cheated and looked at the result from the fread command. If this string is null, it means that nothing was read from the file so we can presume we are at the end.


aspect@aspectscripting.com
 
I'm not sure that will work for me. I have a file with 165 records and I need positions 235-236 (based on a file layout) of every record. There are 1298 columns in the file. I'd like fseek to always start on 235 for every record. I was able to get it to read the first record but I can't get it to read line-by-line. Can I increment fseek by 1298 everytime? I figured if I set the pointer to position 235 and then added 1298, it would go to position 235 of the next record. I can email you a few records from the file

 
I don't see why my sample shouldn't work for your file, you'll just need to change the values in the two fseek commands. Since my sample doesn't perform any file reads via fgets, it doesn't have to worry about the 256-byte string limit. The first fseek should have a value of 234 and the second fseek I would try 1298 and see if that gives you the two characters you are looking for on the second and subsequent reads.

aspect@aspectscripting.com
 
I basically need these last two numbers ("05") from every line. Here are the first 136 columns (line wrapped)

CONTER, STENNIS J 21 NEELY ST APT 407 MEMPHIS MN38105 5262685 020502020505070705

However, there are a total of 1298 columns. What I'd like to do is read column 235 and 236 from each of the 165 records.
 
Does it matter if it has spaces and tabs? I opened it in UltraEdit and it went up to 1543 columns with the tabs. Either way, I think it's only going to work if I can get it to start at the beginning of every line.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top