udfFileOpenReverse
udfFileReadReverse
udfFileCloseReverse
hdl udfFileOpenReverse (str)
str udfFileReadReverse (hdl)
hdl udfFileCloseReverse (hdl)
;==========================================================================================================================================
; How to read a text file backwards?
;------------------------------------------------------------------------------------------------------------------------------------------
; The following set of three user defined functions provides backward reading of a text file.
; That means the last line of the textfile will be returned first.
; When the upper bound of the file is reached, the string *BOF* will be returned.
; The functions are designed to work with CRLF terminated lines only.
;==========================================================================================================================================

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfFileOpenReverse (strFilename)
intFileSize = FileSize (strFilename)
hdlFR = BinaryAlloc (8 + intFileSize)
BinaryReadEx (hdlFR, 6, strFilename, 0, intFileSize)
If BinaryPeek2 (hdlFR, 4 + intFileSize) != 2573 Then BinaryPoke2 (hdlFR, 6 + intFileSize, 2573)
If BinaryPeek2 (hdlFR, 6) != 2573 Then BinaryPoke2 (hdlFR, 4, 2573)
intGlobalOffset = 7 + intFileSize
BinaryPoke4 (hdlFR, 0, intGlobalOffset)
Return hdlFR
;..........................................................................................................................................
; This UDF "udfFileOpenReverse" opens a text file for reading.
; The EOL character must be the CRLF sequence.
; The function returns a handle to the "reversed" file, that is temporarily completely stored into a binary buffer.
; The returning handle is actually the handle to the underlying binary buffer.
; This handle must be used in the "udfFileReadReverse" and "udfFileCloseReverse" functions.
;..........................................................................................................................................
; Usage of binary buffer:
; BufferSize = FileSize + 8 byte.
; Reserved: byte 0..3 for pointer intGlobalOffset.
; Reserved: byte 4..5 for one extra opening CRLF.
; Reserved: 2 byte at end of file stream for extra closing CRLF.
;
; 1. Read file into buffer offset 6.
; 2. Add CRLF at end if it does not exist.
; 3. Add CRLF at beginning if it does not exist.
; 4. Set pointer intGlobalOffset to the end of buffer.
;
; The @CRLF string contant is used as a 16-bit integer value: CRLF = 2573 = 13 + 10*256
;..........................................................................................................................................
; This function is based on a #DefineSubroutine proposal by Guido 02/02, published in the WinBatch forum.
; Modified by Detlev Dalitz.20031025
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfFileReadReverse (hdlFR)
intGlobalOffset = BinaryPeek4 (hdlFR, 0)
intOffsetR = BinaryIndexEx (hdlFR, intGlobalOffset, @CRLF, @BACKSCAN, @FALSE)
If intOffsetR < 5 Then Return "*BOF*"
intOffsetL = BinaryIndexEx (hdlFR, intOffsetR, @CRLF, @BACKSCAN, @FALSE)
If intOffsetL < 0 Then Return "*BOF*"
strLine = BinaryPeekStr (hdlFR, 2 + intOffsetL, intOffsetR - intOffsetL)
intGlobalOffset = 2 + intOffsetL
BinaryPoke4 (hdlFR, 0, intGlobalOffset)
If strLine == @CRLF Then Return ""
Return strLine
;..........................................................................................................................................
; This UDF "udfFileReadReverse" reads data from a file, line by line.
; The handle hFileReverse must be the same that was returned by udfFileOpenReverse.                              ;
;..........................................................................................................................................
; This function is based on a subroutine related proposal by Guido 02/02, published in the WinBatch forum.
; Modified by Detlev Dalitz.20031025
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfFileCloseReverse (hdlFR)
Return BinaryFree (hdlFR)
;..........................................................................................................................................
; This UDF "udfFileCloseReverse" frees the allocated binary buffer, that means file access will be closed.
; The handle hdlFileReverse must be the same that was returned by udfFileOpenReverse.
;..........................................................................................................................................
; This function is based on a subroutine related proposal by Guido 02/02, published in the WinBatch forum.
; Modified by Detlev Dalitz.20031025
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


; Test.

:Test1
; Get last 10 lines of a file.
strFilename = IntControl (1004, 0, 0, 0, 0) ; We use this script as test input file.

hdlFR = udfFileOpenReverse (strFilename)
intCount = 0
While intCount < 10
   strLine = udfFileReadReverse (hdlFR)
   If strLine == "*BOF*" Then Break
   intCount = intCount + 1
   Message (intCount, strLine)
EndWhile
hdlFR = udfFileCloseReverse (hdlFR)

Message ("*BOF*", "Ready.")


:Test2
; Read through entire file.
strFilename = IntControl (1004, 0, 0, 0, 0) ; We use this script as test input file.
BoxOpen ("Demo: How to read a text file backwards?", "")

hdlFR = udfFileOpenReverse (strFilename)
intCount = 0
While @TRUE
   strLine = udfFileReadReverse (hdlFR)
   BoxTitle (intCount)
   BoxText (strLine)
   If strLine == "*BOF*" Then Break
   intCount = intCount + 1
   TimeDelay (0.1)
EndWhile
hdlFR = udfFileCloseReverse (hdlFR)

BoxShut ()
Exit
;==========================================================================================================================================