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