Retrieve last line form a file
Keywords: line last extract BinaryPeekstr
Question:
One DOS application creates a report and saves it to a disk file. I want to read that file and take the TOTAL which is at the end of the report. If I read the file with "FileRead", I have to read record by record until the last record, but that takes to much time because the report is big (2 MB). Can you tell me another method to reach the end of file without reading the file record by record?Answer:
The Binary functions can accomplish this quickly. Here is an example of code using the Binary functions to extract the last line from a file ignoring any extra CRLFs.
file="C:\Temp\abc.txt" fsize=FileSize(file) buffer=BinaryAlloc(fsize) ;read file into binary buffer BinaryRead(buffer,file) endoffile=BinaryEODGet(buffer)-1 While 1 ;locate lines by getting pointers to @CRLFS beginptr=BinaryIndexEx(buffer,endoffile,@CRLF,@BACKSCAN,0) if beginptr != '-1' endptr=endoffile-beginptr+1 lastline=BinaryPeekStr(buffer,beginptr,endptr) if lastline=="" || lastline==@CRLF endoffile=endoffile-2 continue endif ;trim @CLRF off string lastline=strReplace(lastline,@CRLF,'') message("Last Line",lastline) break else message("CRLF Not Found"," Not a valid ascii file.") break endif endwhile BinaryFree(buffer) message("Last line retriever","Done")And here is a UDF to do it:
;------------------------------------------------------------------------------------------------------------------------------------------ If ItemLocate("udffilereadlastline",IntControl(73,103,0,0,0),@TAB) Then Goto skip_udffilereadlastline #DefineFunction udfFileReadLastLine (sFilename) sLine = "" iFilesize = FileSize(sFilename) If iFilesize iBBsize = 8192 ; Assumption: 8 kByte buffer, will cover some lines. hBB = BinaryAlloc(iBBsize) If BinaryReadEx(hBB,0,sFilename,Max(0,iFileSize-iBBsize),iBBsize) BinaryReplace(hBB,@CRLF,@LF,@TRUE) BinaryReplace(hBB,@CR,"",@TRUE) iEod = BinaryEodGet(hBB)-1 iLf = BinaryIndexEx(hBB,iEod,@LF,@BACKSCAN,@TRUE) Select @TRUE Case (iLf < 0) ; Not a valid textfile or try a larger buffer. Break Case (iLf < iEod) ; Last Line without trailing @LF. sLine = BinaryPeekStr(hBB,iLf+1,iEod) Break Case @TRUE ; Valid Line. iEod = iEod-1 iLf = BinaryIndexEx(hBB,iEod,@LF,@BACKSCAN,@TRUE) sLine = BinaryPeekStr(hBB,iLf+1,iEod-iLf) Break EndSelect EndIf BinaryFree(hBB) EndIf Return (sLine) ;.......................................................................................................................................... ; This Function "udfFileReadLastLine" returns the last line of a textfile. ; ; Detlev Dalitz.20030107 ;.......................................................................................................................................... #EndFunction :skip_udffilereadlastline ;------------------------------------------------------------------------------------------------------------------------------------------ ; --- test --- sFilename = "d:\temp\test.txt" MsgTitle = "Demo udfFileReadLastLine(%sFilename%)" MsgText = StrCat('Last Line = "',udfFileReadLastLine(sFilename),'"') Message(MsgTitle,MsgText) Exit ;------------------------------------------------------------------------------------------------------------------------------------------
Article ID: W14572Filename: Retrieve last line from a File.txt