Jump to content

Save/Load (new format?)


Recommended Posts

Hey there folks!

Task:

  1. I have an array of DllStructs, created with the function DllStructCreate. Let's call the array $structs.
  2. This $structs contains important information for the program.
  3. I want to save my  $structs variable for future use in a file (i.e.: the user closes the program, opens it again and has the option to load a file).
  4. I want to load files which contain a $structs variable, and let the program work with this "loaded" variable.

Questions:

Since I have never done such a thing (saving/loading a file, possibly in a different format from txt or ini), I'd like to know:

  1. Is this possible?
  2. Is my only option to save my $structs in text format? That would require a function which receives a file and interprets the text it has, creating a new $structs with the info it's getting from the file. (I think this could lead to trouble)
  3. I'm worried about security. Since the program will be loading files, I don't want it to crash because the user decided to give it modified files. Is it possible to create a file that's readonly for the user? That would prevent some tampering with the file.
  4. From what I've been reading, I have several functions available for File management, namely FileOpen, FileRead and FileWrite. In a first glance, these appear to be the only functions I need. Do I need more?

 

Thank you for your time!

Cheers!

Link to comment
Share on other sites

1.) Yes

2.) You more likely wish to save the contents of these DllStructs verbatin, i.e. as binary. Doing otherwise would be a pain in the keyboard.

3.) You have all the possibilities offered by your OS for managing file permissions. AutoIt doesn't have much say at this level.

4.) You don't need more.

Let's say you go by my version of 2.). All you have to do is, for every DllStruct of your, define own a container DllStruct having the same byte length and content, then write that to a file open in binary mode. Do the reverse for reads, left as an exercise.

Local $s1 = DllStructCreate("align 1;byte;short;byte;real;align 2;byte[3];align 1; byte[7]")
; populate it
;then save it using this:
Local $bs1 = DllStructCreate("byte[" & DllStructGetSize($s1) & "]", DllStructGetPtr($s1))
; now $bs1 is a "flat" binary piece located at the same address as $s1
Local $h = FileOpen("MyStruct.bin", $FO_OVERWRITE + $FO_BINARY)
FileWrite($h, DllStructGetData($bs1))
; ...

 

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Update:

I've been meddling with the functions I listed before. Creating a file and writing text into was a straightforward task:

_FileCreate("jinx")
$file = FileOpen("jinx", $FO_APPEND)
FileWrite($file, "my jinx are tight!")
FileClose($file)

I then tried writing data in binary format into my file:

Global $bin = Binary($var)
_FileCreate("jinx")
$file = FileOpen("jinx", $FO_BINARY)
FileWrite($file, $bin)
FileClose($file)

Note that $var was previously created with DllStructCreate()

This binary writing proved unsuccessful. Is there anything I'm missing in the second code?

Link to comment
Share on other sites

Read my previous answer.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

@jchd, from what I understood:

For every DllStruct of mine (that is, for every element in my array of DllStructs), I create another DllStruct which has the same byte length and content of the original DllStruct.

Afterwards I write it to a file which was opened with the flags $FO_OVERWRITE+$FO_BINARY. Is that it?

 

Also, from what I understood of your code:

Local $s1 = DllStructCreate("align 1;byte;short;byte;real;align 2;byte[3];align 1; byte[7]")

I'm assuming this is merely an example, and thus the DllStruct's content is irrelevant. In the test I'm doing, I used:

Global $var = DllStructCreate("struct;char name[10];int age;bool isMale;endstruct")

Since I used "struct"&"endstruct" to make a C like struct, from what I read this does implicit structure alignments.

 

Local $bs1 = DllStructCreate("byte[" & DllStructGetSize($s1) & "]", DllStructGetPtr($s1))
; now $bs1 is a "flat" binary piece located at the same address as $s1

This looks like a wrapper to me. You're creating a DllStruct with a byte[] array long enough to contain the previous DllStruct. You also give the function a pointer, hence the comment.

 

Local $h = FileOpen("MyStruct.bin", $FO_OVERWRITE + $FO_BINARY)
FileWrite($h, DllStructGetData($bs1))

From what I see, instead of passing the variable $bs1, you passed its data. Why was that?

By the way, DllStructGetData needs a second parameter, 1. DllStructGetData($bs1, 1)

Edited by Razraal
amended some details
Link to comment
Share on other sites

Yes to every point. I was trying to illustrate that alignment may play a role in some cases. Also yes to my omission of the required last parameter to the function (I wrote it on the fly without trying to try it), sorry for that.

I prefer going the pedestrian way and grab the binary content explicitely. I have found no firm specification that trying to FileRead or FileWrite a DllStruct variable directly will work in all past, present and future AutoIt versions. If you can go without the "conversion", just do.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Up until now, doing the write task is solved.

However, doing the read task is troublesome:

$file = FileOpen("myfile")
$var = FileRead($file) ;This is now the stream of bytes that were stored

Now I need to divide my $var into chunks of bytes and convert bytes into the specific things I need (ints, strings, booleans, arrays), according to the struct.

In the case of the example struct I posted above, how would I do that?

Link to comment
Share on other sites

Reversewise from writing: copy the binary data read from file open in binary mode into a byte[] structure of the required length and make a union of this structure with the actual one you need. This is the opposite order from what was made when writing.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

  • 5 years later...

Hi I want to do the same and I couldn't get it to work. Here is what I understood I should do from reading this post :

Local $sStruct = 'int'
Local $tStruct = DllStructCreate($sStruct)
DllStructSetData($tStruct, 1, 10)

Local $bin = SaveDllStruct($tStruct)
$tStruct2 = LoadDllStruct($bin, $sStruct)

_WinAPI_DisplayStruct($tStruct, $sStruct)
_WinAPI_DisplayStruct($tStruct2, $sStruct)


Func SaveDllStruct($tStruct)
    Local $bs1 = DllStructCreate("byte[" & DllStructGetSize($tStruct) & "]", DllStructGetPtr($tStruct))
    Return DllStructGetData($bs1, 1)
EndFunc

Func LoadDllStruct($bin, $sStruct)
    Local $bs1 = DllStructCreate("byte[" & BinaryLen($bin) & "]")
    DllStructSetData($bs1, 1, $bin)
    Return DllStructCreate($sStruct, DllStructGetPtr($bs1))
EndFunc

But the _WinAPI_DisplayStruct() always shows me different content for the 2 structures.

Would someone have an idea how to do that correctly ? 

Thanks

Link to comment
Share on other sites

Nevermind it works now :

Local $String = "int;uint"
Local $Struct = DllStructCreate($String)
DllStructSetData($Struct, 1, 5)
DllStructSetData($Struct, 2, 10)

Local $bin = SaveDllStruct($Struct)
Local $Struct2 = LoadDllStruct($bin, $String)

_WinAPI_DisplayStruct($Struct, $String)
_WinAPI_DisplayStruct($Struct2, $String)

Func SaveDllStruct($Struct)
    Local $bs1 = DllStructCreate("byte[" & DllStructGetSize($Struct) & "]", DllStructGetPtr($Struct))
    Return DllStructGetData($bs1, 1)
EndFunc

Func LoadDllStruct($bin, $String)
    Local $bs1 = DllStructCreate($String)
    Local $bs2 = DllStructCreate("byte[" & BinaryLen($bin) & "]", DllStructGetPtr($bs1))
    DllStructSetData($bs2, 1, $bin)
    Return $bs1
EndFunc

 

Link to comment
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
 Share

×
×
  • Create New...