Sign in to follow this  
Followers 0
EddieBoy

FileSetPos FileRead question

12 posts in this topic

#1 ·  Posted (edited)

I'm trying to read multiple 4 byte long chunks of data from a file into a listview box using FileSetPos FileRead commands.

The number of 4byte chunks varies so I set up a DO loop that: reads, enters into listbox, FileSetPos +4, repeat until all 4byte chunks have been entered.

$Loaded_Data = FileOpen($Load_Location, 16)
;. . .

$FX_Num = n ;number of 4byte chunks to read
FileSetPos ( $Loaded_Data, $Chunk_Begin, 0 )
Do
    $4Byte_Chunk = FileRead($Loaded_Data, 4)
    $FX_Time = BinaryMid($4Byte_Chunk,1,1)
    $FX_Num = BinaryMid($4Byte_Chunk,2,1)                           
    $FX_Slot = Int(BinaryMid($4Byte_Chunk,3,2))                         
    GUICtrlCreateListViewItem(int($FX_Time) &"|"& $FX_Slot & "|" & int($FX_Num),$List)
    ;moves file 4 bytes ahead to next chunk
    FileSetPos ( $Loaded_Data,4, 1 )
    $4Byte_Num = int($4Byte_Num) -1
Until $FX_Num = 0

Problem is, this FileRead is advancing 8 bytes each loop, so if it's reading a file with hex:

00000001 00000002 00000003

it returns

00000001

00000003

Does FileRead move the FilePosition to the end of the read?

EDIT: The conclusion is that FileRead does move the current FilePosition to the end of the read. So if using

FileRead($File,4)

FileSetPos($File,4, 1)

FileRead($File,4)

the second read will begin 8 bytes after where the first read began. The Help File doesn't really mention that.

Edited by EddieBoy

Share this post


Link to post
Share on other sites



Why don't you just read the whole file to a string and then process this string? This will be much faster.

How big is your file?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

This is code for an 'Enemy AI Editor" for a game. The AI files are very small, under 1kb, but they contain different data types that each have to be handled differently (floating point, text, binary). These 4byte chunks are just one section of the file and I'm using a loop to load them because each AI file has a different number of chunks.

I was under the impression that $x=FileOpen() loaded the file in RAM. If there's a faster way, I'm all for it, but I'm a complete newbie so I'm just happy to get anything to work. Do you mean load the whole file it into an array and then process it? :mellow:

Edited by EddieBoy

Share this post


Link to post
Share on other sites

This is code for an 'Enemy AI Editor" for a game.

I'm not very familiar with computer games so please make sure you follow the forum rules.

FileOpen doesn't read a file it just opens the file and returns a handle. FileRead, FileReadLine or _FileReadToArray read a file.

Try FileRead to read the file into a variable and then split and process the content.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

I'm not very familiar with computer games so please make sure you follow the forum rules.

FileOpen doesn't read a file it just opens the file and returns a handle. FileRead, FileReadLine or _FileReadToArray read a file.

Try FileRead to read the file into a variable and then split and process the content.

I don't think what I'm working on comes close to violating the rules :mellow: It's just a GUI file editor tool; it's not even actually for a game, but for a game-making software's enemy files. The editor's purpose is to give people access to settings that can't normally be edited through the game-making software's normal GUI.

Thank you very much for the advice, I'll try to rework my 'Load File' setup using the whole file read into a variable.

It would still be good to know for future reference if FileRead moves the 'File current Position' to the end of the read-length. :)

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

This should answer your question:

The script creates a new file with 8 bytes content. The file is closed and reopened for read access. 4 bytes are read and written to the console, then another 4 bytes are read and written to the console.

You should get:

Read 1: 1234
Read 2: 5678
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Thank you for taking the time to help Water :mellow: I don't seem to be getting the results you describe. I'm going to rewrite to lose the 'FileRead', but I made a sample to illustrate what I am experiencing with the current setup. Attached is a demo-file to load which just has:

0x00000000 01000000 02000000 03000000 04000000 05000000 06000000 07000000

I think what I'm getting (as in your example Water) is:

Read 1: 1234

Read 2: 9ABC

#include <GUIConstantsEx.au3>
#include <GuiListView.au3>

GUICreate("", 250, 250)
$List = GUICtrlCreateListView("1", 15, 5, 185, 145)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 158)
$Load_Button = GUICtrlCreateButton("Load", 15, 170, 60, 40)
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit


        Case $Load_Button

            $Load_Location = FileOpenDialog("", "", "(*.txt)", 1)
            $Loaded_Data = FileOpen($Load_Location, 16)
            $FX_Num = 4
            FileSetPos($Loaded_Data, 0x4, 0)
            Do
                $Temp = FileRead($Loaded_Data, 4)
                GUICtrlCreateListViewItem($Temp, $List)
                FileSetPos($Loaded_Data, 4, 1)
                $FX_Num = Int($FX_Num) - 1
            Until $FX_Num = 0

            FileClose($Loaded_Data)

    EndSwitch
WEnd

DEMO.TXT

Share this post


Link to post
Share on other sites

Did I forget to post the example script in my last post?

If yes, here it is:

$hFile = FileOpen("C:\Temp\TestAi.txt", 2)
FileWrite($hFile, "12345678")
FileClose($hFile)
$hFile = FileOpen("C:\Temp\TestAi.txt", 0)
ConsoleWrite("Read 1: " & FileRead($hFile, "4") & @CRLF)
ConsoleWrite("Read 2: " & FileRead($hFile, "4") & @CRLF)
FileClose($hFile)

It shows that if you read 4 bytes and then read again you'll start with byte 5.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Ah, I understand what you were saying better now. I thought the "script" you were referring to was what I posted earlier (which had the FileRead and FileSetPos +4), but your script clears it up. I'll add the conclusion to the top post incase some other dumb newbie like ever runs into the same thing. Thanks very much Water! :mellow:

Share this post


Link to post
Share on other sites

I played a bit with your script and I think this is what you need:

#include 
#include 

GUICreate("", 250, 250)
$List = GUICtrlCreateListView("1", 15, 5, 185, 145)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 158)
$Load_Button = GUICtrlCreateButton("Load", 15, 170, 60, 40)
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Load_Button
            $Load_Location = FileOpenDialog("", "", "(*.txt)", 1)
            $Loaded_Data = FileOpen($Load_Location, 16)
            While 1
                $Temp = FileRead($Loaded_Data, 4)
                If @error then ExitLoop
                GUICtrlCreateListViewItem($Temp, $List)
            Wend
            FileClose($Loaded_Data)
    EndSwitch
WEnd

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

I played a bit with your script and I think this is what you need:

I hadn't considered using @error to end a loop. It seems it stops when the file ends which would be great for reading a single variable length file into a control. In this case, the example I posted was just a simplified extracted snippet for illustration. In the actual files, this data decides which sound effects are played during each animation sequence (attacking, walking etc) so I have to set when the loop stops or it will continue reading into the sounds that belong to the next animation. The actual editor has multiple ListView boxes- one for each animation. I came up with this which has slightly less 'FileReads' than before

FileSetPos($Loaded_Enemy_PRF_Data, 0x1cc, 0) ;read # of sound entries for this animation
$SND_Num = FileRead($Loaded_Enemy_PRF_Data, 1)

If $SND_Num > 0 Then ;only continue if sounds exists

    FileSetPos($Loaded_Enemy_PRF_Data, 0x1ce, 0) ;read where sounds for this animation begin
    $Temp = FileRead($Loaded_Enemy_PRF_Data, 2)

    FileSetPos($Loaded_Enemy_PRF_Data, $Temp, 0) ;Jump to where sounds for this animation begin
    $Temp = FileRead($Loaded_Enemy_PRF_Data, 4 * Int($Temp_SND_Num)) ;read all 4byte Sound chunks for this animation into $Temp
    $Advance = 0 ;setup variable that will be used to advnce 4 bytes each loop
    Do; loop each 4byte sound-chunk into ListView
        $SND_Time = BinaryMid($Temp, 1 + $Advance, 1)
        $SND_Pitch = BinaryMid($Temp, 2 + $Advance, 1)
        $SND_File = BinaryMid($Temp, 3 + $Advance, 2)
        GUICtrlCreateListViewItem($SND_Time & "|" & $SND_File & "|" & $SND_Pitch, $Defending_SND_List)
        $Temp_SND_Num = Int($Temp_SND_Num) - 1 ;reduce remaining sounds by 1 each loop
        $Advance = $Advance + 4 ;advance BinaryMid() read location by 4 bytes each loop
    Until $SND_Num = 0; stop when all sound-blocks are entered in listview
EndIf

Now that I know "OpenFile" doesn't copy the file to RAM, I'm trying to rework the code wherever I can to limit FileReads.

Zedna- thanks :mellow: The example in that post sounds similar to what I'm trying to do so it might be a big help. I'm just a beginner so I'll have to study it some. Autoit really is a great place to begin learning programming!

Edited by EddieBoy

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