WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Binary Functions

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

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
;------------------------------------------------------------------------------------------------------------------------------------------

Here is a code sample to read the last {n} of line from a file:

#DefineFunction udfFileReadLastLines(sFilename, iCount)
sLines = ""
iFilesize = FileSize(sFilename)
If iFilesize
   iBBsize = 32768 ; Assumption: 32 kByte buffer, will cover some lines. Increase to fit your needs.
   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)
      iLf = iEod
      For x = 1 To iCount+1
         iLf = BinaryIndexEx(hBB,iLf,@LF,@BACKSCAN,@TRUE)
         If iLF == -1 Then Break
         iLf = iLf-1
      Next
      If iLf < iEod
         sLines = BinaryPeekStr(hBB,iLf+1,iEod)
      Else
       Pause('Notice','Houston we have a problem')
      EndIf

   EndIf
   BinaryFree(hBB)
EndIf
Return (sLines)
#EndFunction

sFilename = "C:\TEMP\Data\Customers.txt"
LastLines = udfFileReadLastLines(sFilename, 5)  ;Read last 30 lines
Message(sFilename,LastLines)
Exit

Article ID:   W14572
Filename:   Retrieve last line from a File.txt
File Created: 2014:02:11:15:58:46
Last Updated: 2014:02:11:15:58:46