The following was inspired by this thread and Horst Schaeffer's filebuffer code.
I created a full mini library!
It's not really that optimized, but should be platform independent.
It lets you read an entire text file into memory,
counts the lines, creates it's own static array, keeps track of the max string length.
And let you retrive the strings easily.
or optionaly just get the length of a string,
or even a direct pointer to a string (need to use PeekS() in that case)
It is able to open a file on it's own,
read from a allready open file (make sure to FileSeek pointer is at proper place first),
or open a file but reuse a existing fileID.
I haven't checked how Rings did his routines, most likely they are better optimized.
But anyway, better to have too many examples than to few right?
Have fun peeps!
Warning! Make sure you use MaxLengthTextMem() to check max string length, because it is possible to return strings as large as the system memory allows.
Also be aware that there is no limit to the number of lines, or size of a file.
Only limitations should be available memory and PureBasics internal size restrictions on files and memory and values.
Also note that you can have multiple files loaded at the same time.
Note! No string editing or replacement is possible, except "In Place" editing or replacement. This is the reason that PointerTextMem() and LengthTextMem() exist, to allow advanced manipulation of the loaded text.
EDIT: Added automatic 0 terminator to the strings (this means the EOF is changed),
this should make PointerTextMem() more interesting to use with libraries and functions and api and GUI calls that expect strings to be 0 terminated.
Also fixed a bug with PointerTextMem().
LoadText.pbi
Code: Select all
Procedure.l LoadTextMem(fileID,file.s) ; Returns 0 if not enough memory or open failed!
Protected fileID,fhdl,*buffer,Size,readsize,*ptr.BYTE,*ptrend,Lines,c,n,*strptr,Length,maxlength
If file
fhdl=ReadFile(fileID,file)
If fhdl=false : ProcedureReturn 0 : EndIf
Else
If IsFile(fhdl)=false : ProcedureReturn 0 : EndIf
UseFile(fhdl)
fhdl=fileID
EndIf
If fhdl
Size=Lof()
If Size>0
*buffer=AllocateMemory(Size+16)
If *buffer
readsize=ReadData(*buffer+16,Size) ;header is 16 bytes
PokeL(*buffer,readsize) ; Text file size
*ptr=*buffer+16
*ptrend=*ptr+readsize
If *ptr<*ptrend
Lines=0
While *ptr<*ptrend
While *ptr<*ptrend
c=*ptr\b : *ptr+1
If c=13 : Break : EndIf
If c=10 : Break : EndIf
Wend
If *ptr<*ptrend
n=*ptr\b
If n+c=23 : *ptr+1 : EndIf
Lines+1
EndIf
Wend
PokeL(*buffer+4,Lines) ; Number of lines
EndIf
*index=AllocateMemory(Lines*8)
If *index
PokeL(*buffer+8,*index) ; Index pointer
*ptr=*buffer+16
*ptrend=*ptr+readsize
If *ptr<*ptrend
Lines=0
While *ptr<*ptrend
Length=0
*strptr=*ptr
While *ptr<*ptrend
c=*ptr\b : *ptr+1
If c=13 : Break : EndIf
If c=10 : Break : EndIf
Length+1
Wend
If *ptr<*ptrend
n=*ptr\b
If n+c=23 : *ptr+1 : EndIf
PokeL(*index+(Lines*8),*strptr)
PokeL((*index+4)+(Lines*8),Length)
PokeB((*strptr+Length)+1,0) ; places a 0 terminator where the EOF is.
Lines+1
If maxlength<Length : maxlength=Length : EndIf
EndIf
Wend
EndIf
PokeL(*buffer+12,maxlength) ; Maximum string length
Else
FreeMemory(*buffer)
ProcedureReturn 0
EndIf
ProcedureReturn *buffer
EndIf
EndIf
If file Or fileID=#PB_Any : CloseFile(fhdl) : EndIf
EndIf
ProcedureReturn 0
EndProcedure
Procedure FreeTextMem(*buffer) ; Free text buffer and index memory
Protected *index
If *buffer
*index=PeekL(*buffer+8)
If *index
FreeMemory(*index)
EndIf
FreeMemory(*buffer)
EndIf
EndProcedure
Procedure.l CountTextMem(*buffer) ; Return number of lines
Protected *index
If *buffer
ProcedureReturn PeekL(*buffer+4)
EndIf
ProcedureReturn 0
EndProcedure
Procedure.l MaxLengthTextMem(*buffer) ; Return length of the longest string
Protected *index
If *buffer
ProcedureReturn PeekL(*buffer+12)
EndIf
ProcedureReturn 0
EndProcedure
Procedure.s ReadTextMem(*buffer,line) ; Return specified line as string, "" if error or empty, range 0 to CountTextMem(*buffer)-1
Protected *index,Length,*strptr
If *buffer
*index=PeekL(*buffer+8)
*strptr=*index+(line*8)
Length=PeekL(*strptr+4)
If Length>0
ProcedureReturn PeekS(PeekL(*strptr),Length)
EndIf
EndIf
ProcedureReturn ""
EndProcedure
Procedure.l PointerTextMem(*buffer,line) ; Return pointer to string, 0 if error, range 0 to CountTextMem(*buffer)-1
Protected *index,Length,*strptr
If *buffer
*index=PeekL(*buffer+8)
ProcedureReturn PeekL(*index+(line*8))
EndIf
ProcedureReturn 0
EndProcedure
Procedure.l LengthTextMem(*buffer,line) ; Return length of string, 0 if error or empty, range 0 to CountTextMem(*buffer)-1
Protected *index
If *buffer
*index=PeekL(*buffer+8)
ProcedureReturn PeekL((*index+(line*8))+4)
EndIf
ProcedureReturn 0
EndProcedure
LoadTextTest.pb
Code: Select all
XIncludeFile "LoadText.pbi"
#TextFile=0
TextFile$=OpenFileRequester("Please choose file to load","F:\","Text (*.txt)|*.txt",0)
If TextFile$
*textptr=LoadTextMem(#TextFile,TextFile$)
linestotal=CountTextMem(*textptr)
Debug "Number of lines: "+Str(linestotal)
Debug "Longest line: "+Str(MaxLengthTextMem(*textptr))
line=0
While line<linestotal
Debug ReadTextMem(*textptr,line)
line+1
Wend
FreeTextMem(*textptr)
EndIf