Page 1 of 1
Reading string from file at specific line
Posted: Wed Apr 05, 2006 1:20 pm
by Waussie
Hello,
I'm trying to read a stringvalue from a file.
The string is always located at line 15 of the file, but lines are not always of the same length, so I can't use seek.
The file isn't generated by me, so i can't change it in any way.
I use readstring at the moment, but it makes me read 15 lines, before i got the right line...
Is there any way to make a Lineseek, or something?
Thnx in advance for all suggestions.
Posted: Wed Apr 05, 2006 3:05 pm
by Trond
Code: Select all
Procedure NotL(Val)
ProcedureReturn (Not Val)
EndProcedure
ReadFile(0, "c:\HelloWorldApp.java")
I = 0
While I < 14 And NotL(Eof(0))
If ReadByte(0) = 10
I + 1
EndIf
Wend
Debug ReadString(0)
(The Not operator is halfway broken.)
Posted: Wed Apr 05, 2006 3:07 pm
by Bonne_den_kule
Why make it so hard Trond?
Code: Select all
ReadFile(0, "c:\HelloWorldApp.java")
I = 0
While I < 14 And Eof(0)=0
If ReadByte(0) = 10
I + 1
EndIf
Wend
Debug ReadString(0)
Posted: Wed Apr 05, 2006 3:16 pm
by Fred
you can also just do a loop of readstring() without affecting the value, it should be quite fast:
Code: Select all
ReadFile(0, "c:\HelloWorldApp.java")
For k=1 to 14
ReadString(0)
Next
Debug ReadString(0)
Posted: Wed Apr 05, 2006 3:39 pm
by Waussie
Hmm, searching for a linefeed or using readstring, don't know what's faster, Trond. :roll:
That's almost exactly what I had Fred
But it does give me a brainwave getting the stringcheck not to be checked at first 14 lines...
Posted: Wed Apr 05, 2006 5:29 pm
by Trond
ReadByte() is faster.
Posted: Wed Apr 05, 2006 9:38 pm
by Dare2
Doing 15 ReadStrings seems the simplest way.
Anyhow, just for fun, here is another way.
Code: Select all
src.s = "Path\to\a\file\with\ascii.txt"
line.s = "??? Did not read file"
lineToRead = 15
lineToRead - 1 ; Index of preceding EOL
sz = FileSize(src)
If sz > 0
ReadFile(1, src)
If LineToRead = 0
line = ReadString(1)
Else
buf.s = Space(sz+1)
ReadData(1, @buf, sz)
p=1
For i = 1 To lineToRead
p = FindString(buf, #LF$, p) + 1 ; This Assumes either Chr(13)+Chr(10) or Chr(10) eol
If p = 1 ; If eol in your file is just Chr(13), use #CR$ instead
Break
EndIf
Next
If p <> 1
px = FindString(buf, #LF$, p)
line = Mid(buf, p, px-p-1) ; If just Chr(10) [or JUST Chr(13)] eol, drop the "-1"
Else
line = "*** not enough lines ***"
EndIf
EndIf
CloseFile(1)
EndIf
Debug line
Posted: Thu Apr 06, 2006 4:02 pm
by Trond
Very fast on small files:
Code: Select all
Procedure.s Test4()
ReadFile(0, "c:\HelloWorldApp.java")
Ptr.l
Ptr = AllocateMemory(Lof(0))
ReadData(0, Ptr, Lof(0))
A.s = StringField(PeekS(Ptr), 15, #CRLF$)
FreeMemory(Ptr)
CloseFile(0)
ProcedureReturn A
EndProcedure
Posted: Thu Apr 06, 2006 4:10 pm
by GedB
Waussie,
Your problem is that you don't know how long the lines are. To find that out, you have to read through the whole thing finding the line breaks.
For example, if the first 15 lines are empty you would only have to seek to the 16th Byte.
So theres is no way around it. If the linebreaks can be anywhere, your going to have to read through every byte until you reach the 15th line.
Posted: Thu Apr 06, 2006 4:33 pm
by Dare2
Trond wrote:Very fast on small files:
And also very small and readable code. Now I would love to top your effort but short of going the asm route I can't think of a winning approach.
Darn!
Anyone?