Sign in to follow this  
Followers 0
Eru

_FileCountLines on an Open File in Windows 7

8 posts in this topic

#1 ·  Posted (edited)

I play a very old game called Ultima Online on a private server, and one of the things that bothers me about it is that there's no built in chat log. I wrote a chatlog program that reads all the information written to a log file that is filled mostly with crap. (Skill messages, spam, etc.) So, now that the background and purpose is out of the way, here's the meat of the problem:

I use _FileCountLines($LogFile) to get the amount of lines in the log file for parsing reasons. This has worked fantastically when I was scripting and compiling with AutoIt v 3.3.2.0 on Windows Vista. However, since I've upgraded to AutoIt 3.3.4.0 and Windows 7, _FileCountLines no longer returns the number of lines and instead returns 0 (the error code for failure).

-edit-

I've found that any file operations don't seem to work on the file. FileOpen, FileReadLine, etc. :D

On a related note, I still have the old version that is compiled on AutoIt 3.3.2.0 and it will read the lines while the program is open just fine.

-/edit-

I've found that it ONLY has this error if the game is open, and if I close the game, everything functions normally. If I compile and run the chatlog as Administrator, it still returns 0. So, my question is, how can I get it to count the number of lines in the file while the program is open?

The solution that I've come up with is to copy the file to @TempDir access it from there, and then delete it when I'm done, but that seems like a lot of excessive reading/writing for something that used to just work from the existing file, especially when the log gets to be large.

Here's the info on the _FileCountLines function:

; #FUNCTION# ====================================================================================================================

; Name...........: _FileCountLines

; Description ...: Returns the number of lines in the specified file.

; Syntax.........: _FileCountLines($sFilePath)

; Parameters ....: $sFilePath - Path and filename of the file to be read

; Return values .: Success - Returns number of lines in the file.

; Failure - Returns a 0

; @Error - 0 = No error.

; |1 = File cannot be opened or found.

; Author ........: Tylo <tylo at start dot no>

; Modified.......: Xenobiologist, Gary

; Remarks .......: It does not count a final @LF as a line.

; Related .......:

; Link ..........:

; Example .......: Yes

; ===============================================================================================================================

And here's a snippet of code, though I'm 99.999% sure there's nothing wrong with it aside from being sloppy as heck:

Func LoadSavedLog()
    Local $Parse = FileOpen($LogFile,0)
    Local $TotalSize = _FileCountLines($LogFile)
    ConsoleWrite(@CRLF & $LogFile & " Size: " & $TotalSize & @CRLF)
    FileReadLine($Parse,$LogFileSize-1)
    Do
        For $iLFS = 1 To 50 Step 1
            $ParsedLine = FileReadLine($Parse)
            If @error = -1 Then
                $ExitLoop=1
                ExitLoop
            EndIf
            Scrub($ParsedLine)
            $LogFileSize = $LogFileSize+1
            ConsoleWrite("LoadSavedLog Progress: " & $LogFileSize & " / " & $TotalSize & @CRLF)
            GUI()
        Next
            GUICtrlSetData($Progress,($LogFileSize/$TotalSize)*100)
            IniWrite($IniFile,"Saved","LogFileSize",$LogFileSize)
            If $ExitLoop = 1 Then ExitLoop
    Until $LogFileSize = $TotalSize
    IniWrite($IniFile,"Saved","LogFileSize",$LogFileSize)
    GUICtrlSetData($Progress,100)
    FileClose($Parse)
EndFunc

Incidentally, is it safe to just use $i in all your For loops? I tend to rename them based on their functions, as seen above.

Edited by Eru

Share this post


Link to post
Share on other sites



A file can't be opened twice. You're opening it first with FileOpen but the UDF _FileCountLines also needs to use FileOpen and FileClose to open and read the file. I would suggest you reverse the two lines:

Func LoadSavedLog()
    Local $TotalSize = _FileCountLines($LogFile)
    Local $Parse = FileOpen($LogFile,0)
    
...

Share this post


Link to post
Share on other sites

Thanks for the suggestion, I swapped the two around.

However, the program ran fine before the swap as long as the game was closed, and it still doesn't read the log file with the game open.

Share this post


Link to post
Share on other sites

I would also suggest you rewrite that entire routine to use _FileReadToArray rather than FileOpen. The reason is that this is a live log your are accessing and you have a good chance of creating a file lock problem while processing it. By using _FileReadToArray, you parse each line of the log in memory rather than parsing each line while the log is locked open. I hope I explained that well enough.

Share this post


Link to post
Share on other sites

Incidentally, is it safe to just use $i in all your For loops? I tend to rename them based on their functions, as seen above.

Sorry, missed this bit..

Yes, it's actually good coding.

My preferences are:

$i... for integers

$s... for strings

$h... for handles

$a... for arrays

$o... for objects

etc.

Share this post


Link to post
Share on other sites

I would also suggest you rewrite that entire routine to use _FileReadToArray rather than FileOpen. The reason is that this is a live log your are accessing and you have a good chance of creating a file lock problem while processing it. By using _FileReadToArray, you parse each line of the log in memory rather than parsing each line while the log is locked open. I hope I explained that well enough.

I get what you mean, and that's on my "To Do" list. :D I wrote this before I really knew how much better _FileReadToArray was.

Also, back to the problem at hand, I just went to a different computer that is running windows Vista and the same version of AutoIt I'm trying to use now and compiled it to .exe there. I then pulled the .exe up to the Windows 7 computer and everything works fine.

So, it's probably a problem with compiling AutoIt under Windows 7. I'll see if I can set the compiler to run as Admin or something. *shrug*

Share this post


Link to post
Share on other sites

I found the solution. I just downgraded to version 3.3.2.0 and everything went perfectly.

I guess I should go report a bug or something.

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0