Wilson WindowWare Tech Support

WinBatch WinBatch+Compiler WebBatch
Home | Tech Database | Tech BBS | White Papers | Purchase


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:   W14572
Filename:   Retrieve last line from a File.txt