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 :D

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! :P :D

Anyone?