kiffab Posted August 11, 2012 Posted August 11, 2012 Hi Folks I have to read a text file in, search for a string and once I find it strip all the stuff I don't need out and leave me with a time. I then have to check the most recent time (last line of file) and the time before that (second last line in file). How can I read that second last line? I use StringInStr to locate my keyword then StringLeft to trim. I save this to a temp file (its small - only a handful of lines). I then set a variable for my last line. $lastLine = FileReadLine($file, -1) I thought the second last would just be $secondlastLine = FileReadLine($file -2) but no.... Can anyone help? Thanks.
kaotkbliss Posted August 12, 2012 Posted August 12, 2012 Couldn't you _FileReadToArray($file, $array) then $line = $array[0]-1 $array[$line] should be the 2nd to last line 010101000110100001101001011100110010000001101001011100110010000 001101101011110010010000001110011011010010110011100100001 My Android cat and mouse gamehttps://play.google.com/store/apps/details?id=com.KaosVisions.WhiskersNSqueek We're gonna need another Timmy!
water Posted August 12, 2012 Posted August 12, 2012 I thought the second last would just be $secondlastLine = FileReadLine($file -2) but no....What's the value of @error of $secondlastLine = FileReadLine($file, -2) ConsoleWrite(@error & @CRLF)(you know there was a comma missing in your statement?) My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
water Posted August 12, 2012 Posted August 12, 2012 Just tried it myself. Returns 1 as @error. If you can't use the solution koatbliss suggests you could use FileSetPos to position near the end of the file and process the rest of the file: $hFile = FileOpen("C:temptest.txt") FileSetPos($hFile, -20, 2) ; Go to the end of the file, then go backward 20 characters $sResult = FileRead($hFile) ; Read the rest of the file $aTemp = StringSplit($sResult, @CRLF, 1) ; Split into lines ConsoleWrite("Second to last line: " & $aTemp[$aTemp[0]-1] & @CRLF) ; Display the second to last line My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
Danyfirex Posted August 12, 2012 Posted August 12, 2012 I made this way. A simple Function I do not know, if it is the most effective way, but work Fine. ;A simple example with txt file. Local $file = FileOpen("1.txt", 0) If $file = -1 Then MsgBox(0, "Error", "Unable to open file.") Exit EndIf msgbox(0,"",LSL($file)) FileClose($file) Func LSL($filehandle) local $i=0 While 1 Local $line = FileReadLine($filehandle) If @error = -1 Then ExitLoop $i+=1 WEnd $lastSline=filereadline($filehandle,$i-1) Return $lastSline EndFunc Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
Moderators Melba23 Posted August 12, 2012 Moderators Posted August 12, 2012 Danyfirex, I do not know, if it is the most effective wayIt is very inefficient - because you are reading every line in the file. Take a look at these other ways of doing it: expandcollapse popup#include <File.au3> $sFile = "M:ProgramAutoIt3IncludeWinAPI.au3" ; Adjust to your include path Local $hFile = FileOpen($sFile, 0) If $hFile = -1 Then MsgBox(0, "Error", "Unable to open file.") Exit EndIf MsgBox(0, "", LSL($hFile)) FileClose($hFile) MsgBox(0, "", _Read_Pen_Line()) MsgBox(0, "", _Read_To_Array()) Func LSL($hFilehandle) $iBegin = TimerInit() Local $i = 0 While 1 Local $line = FileReadLine($hFilehandle) If @error = -1 Then ExitLoop $i += 1 WEnd $lastSline = FileReadLine($hFilehandle, $i - 1) ConsoleWrite(TimerDiff($iBegin) & @CRLF) Return $lastSline EndFunc ;==>LSL Func _Read_Pen_Line() ; Count the lines and just read the one we want $iBegin = TimerInit() $iCount = _FileCountLines($sFile) $lastSline = FileReadLine($sFile, $iCount - 1) ConsoleWrite(TimerDiff($iBegin) & @CRLF) Return $lastSline EndFunc Func _Read_To_Array() ; Read into an aray and then just extrat the line we want $iBegin = TimerInit() Local $aLines _FileReadToArray($sFile, $aLines) ConsoleWrite(TimerDiff($iBegin) & @CRLF) Return $aLines[$aLines[0] - 1] EndFunc When I run this I find that the first function takes well over twice as long as the last - and nearly twice as long as the second. I would go for the array version each time. M23 PoojaKrishna 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
Danyfirex Posted August 12, 2012 Posted August 12, 2012 (edited) Danyfirex, It is very inefficient - because you are reading every line in the file. Take a look at these other ways of doing it: expandcollapse popup#include <File.au3> $sFile = "M:ProgramAutoIt3IncludeWinAPI.au3" ; Adjust to your include path Local $hFile = FileOpen($sFile, 0) If $hFile = -1 Then MsgBox(0, "Error", "Unable to open file.") Exit EndIf MsgBox(0, "", LSL($hFile)) FileClose($hFile) MsgBox(0, "", _Read_Pen_Line()) MsgBox(0, "", _Read_To_Array()) Func LSL($hFilehandle) $iBegin = TimerInit() Local $i = 0 While 1 Local $line = FileReadLine($hFilehandle) If @error = -1 Then ExitLoop $i += 1 WEnd $lastSline = FileReadLine($hFilehandle, $i - 1) ConsoleWrite(TimerDiff($iBegin) & @CRLF) Return $lastSline EndFunc ;==>LSL Func _Read_Pen_Line() ; Count the lines and just read the one we want $iBegin = TimerInit() $iCount = _FileCountLines($sFile) $lastSline = FileReadLine($sFile, $iCount - 1) ConsoleWrite(TimerDiff($iBegin) & @CRLF) Return $lastSline EndFunc Func _Read_To_Array() ; Read into an aray and then just extrat the line we want $iBegin = TimerInit() Local $aLines _FileReadToArray($sFile, $aLines) ConsoleWrite(TimerDiff($iBegin) & @CRLF) Return $aLines[$aLines[0] - 1] EndFunc When I run this I find that the first function takes well over twice as long as the last - and nearly twice as long as the second. I would go for the array version each time. M23 You are right M23 my function lose more time because read every line. thank you for clearing up that. Sorry for my english :S Edited August 12, 2012 by Danyfirex Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
Moderators Melba23 Posted August 12, 2012 Moderators Posted August 12, 2012 Danyfirex, Glad I could help. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
GEOSoft Posted August 12, 2012 Posted August 12, 2012 (edited) Danyfirex You should definitly read the help file about how FileReadLine works. Putting it simply; if you tell it for example to read lines 3, 4 and 5 It starts at line 1, jumps down 1 line at a time and returns the line you requested (3) It then jumps back to line 1 and repeats the sequence (1 line at a time) for the next line (4) The process again repeats for line 5 so in reality it has to go through 12 lines to read line 5 in this example. In other words; it doesn't start at 1 then jump to 3 followed by a jump to 4 then 5. That is what makes FileReadLine() so inefficient and makes the array method so much faster. Edited August 12, 2012 by GEOSoft George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
kiffab Posted August 13, 2012 Author Posted August 13, 2012 (edited) Hi Guys Thanks for all the responses. I worked on this yesterday and here's what I did. Files I am reading are < 10 mb in size. Constructive criticism welcome Dim $arrayGC If Not _FileReadToArray($wrappergc,$arrayGC) Then GUICtrlSetData($06_gc_lbl, "No recent full GC") GUICtrlSetData($06_gc_dif_lbl, " No recent full GC") Return EndIf $countForSecondLastGC = UBound($arrayGC)-2 For $x = Ubound($arrayGC) -2 To $countForSecondLastGC Step -1 $secondLastGC = $arrayGC[$x] Next ;Msgbox(0,"",$secondLastGC) $countForLastGC = UBound($arrayGC)-1 For $x = Ubound($arrayGC) -1 To $countForLastGC Step -1 $LastGC = $arrayGC[$x] Next GUICtrlSetData($06_gc_lbl, "Last GC: " & $lastGC) Edited August 13, 2012 by kiffab
kiffab Posted August 13, 2012 Author Posted August 13, 2012 Oh and while I am here I have a question regarding the reading of text files My app will read the file every 30 seconds. If the status of something has changed and it's now "down", my app will write an entry to a database table. This appears to work correctly. However, there is one bug. Sometimes the status will change to "up" briefly when it's actually "down". I have identified the cause of this - it's reading the text file when it's incomplete (i.e. still writing). Is there a way to pause it or something if the file is still being written? I don't want to generate false alerts. Cheers.
water Posted August 13, 2012 Posted August 13, 2012 Why doy ou use a loop?Dim $arrayGC If Not _FileReadToArray($wrappergc, $arrayGC) Then GUICtrlSetData($06_gc_lbl, "No recent full GC") GUICtrlSetData($06_gc_dif_lbl, " No recent full GC") Return EndIf $secondLastGC = $arrayGC[$arrayGC[0]-1] $LastGC = $arrayGC[$arrayGC[0]] GUICtrlSetData($06_gc_lbl, "Last GC: " & $lastGC) My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
water Posted August 13, 2012 Posted August 13, 2012 Which application creates the file? Did you write it yourself or is it a program/script you can't change? My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
kiffab Posted August 13, 2012 Author Posted August 13, 2012 @Water - No real reason, I just thoguht I required one. I will look at your alternative. I am using a batch file to create the log file - it's just pulling from event viewer. @echo off echo wscript.echo ^(Date^(^)-1^)>lastMonth.vbs for /f %%a in ('cscript //nologo lastMonth.vbs') do set ydate1=%%a del lastMonth.vbs set ydate1=%ydate1:/=% set d=%ydate1:~0,2% set m=%ydate1:~2,2% set y=%ydate1:~4,4% set ydate2=%m%/%d%/%y%,01:01:01AM cscript C:scriptseventquery.vbs /l system /v /fi "source eq Service Control Manager" /fi "Id eq 7035 or Id eq 7036" /fi "Datetime gt %ydate2%" > Events.txt
water Posted August 13, 2012 Posted August 13, 2012 In this case I would translate your script to AutoIt and pack everything into a single AutoIt script. My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
kylomas Posted August 13, 2012 Posted August 13, 2012 kiffab, You might adapt the following to quickly read lines from the end of a text file. ; ; ; #include <constants.au3> #include <array.au3> $hFile = FileOpen("your.file.name") if $hfile = -1 then msgbox(0,"Error on open","") local $pos = filesetpos($hfile,-4096,$file_end) $string = FileRead($hFile) FileClose($hFile) $a10 = stringsplit($string,@crlf,3) _arraydisplay($a10) kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill
water Posted August 13, 2012 Posted August 13, 2012 Hi kylomas,that's exactly the solution I've already posted in post My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
kylomas Posted August 13, 2012 Posted August 13, 2012 @water, I AM an idiot, sorry... @kiffab - follow water's advice... kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill
water Posted August 13, 2012 Posted August 13, 2012 I think you have to do more to prove you are an idiot ... it was just an oversight. My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
AZJIO Posted August 13, 2012 Posted August 13, 2012 (edited) #include <FileConstants.au3> $Pos = 1000 $hFile = FileOpen(@ScriptDir & 'file.au3') FileSetPos($hFile, -196, $file_end) $sText = FileRead($hFile) FileClose($hFile) For $i = 1 To 5 $string = _ReadString($Pos, $i) MsgBox(0, -$i, $string) ClipPut($string) Next Func _ReadString(ByRef $Pos, $i) $TmpPos = StringInStr($sText, @CRLF, 0, -$i) $string = StringMid($sText, $TmpPos + 2, $Pos - $TmpPos - 2) $Pos = $TmpPos Return $string EndFunc Edited May 8, 2013 by AZJIO My other projects or all
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now