Thanks to Yu Tang a Japanese translation is now available too.
Using custom objects is great in your applications.It gives you organized and visual way to access global options, configuration data, etc... |
However usally when it is time to load up these objects on start up or save them on exit you have to read in each field one by one from an ini file or from registry values. |
This technique will show you a way that you can save the entire configured object into a binary file and then latter extract the completly configured object with about 3 lines of code. I suspect that you can also use this technique savign objects to a database assuming the column is set for a binary data type. |
Here is an example program that demonstrates the technique. Start up a new standard exe project, paste this source in to the code window and run it. |
This code is deceptivly simple...the thing to notice is the line: Put f,,b f is the filehandle, the empty argument is the start-at offset (BOF) and 'b' is the configured object. We are telling it to write the entire data structure with data to disk. Basically we are creating a memory dump of the structure. Like wise it is worth to note the lines: Dim ha As blah here we are telling the system that 'ha' is actually the datatype "blah" which is composed of 3 strings and an integer value. Then when we tell the system to: Get f, , ha where we are telling it to read the file until the datatype has been filled. Here is a how the file "c:\blah.txt" appears in a hex editor: |
0D 00 4A 75 73 74 20 73 6F 6D 65 20 67 75 79 33 ..Just.some.guy3 00 65 61 74 20 79 75 6D 6D 69 65 73 20 61 6E 64 .eat.yummies.and 20 67 65 74 20 66 61 74 20 6C 69 6B 65 20 73 75 .get.fat.like.su 6D 6F 20 77 72 65 73 74 6C 65 72 20 2A 66 6C 65 mo.wrestler.*fle 78 65 73 2A 3A 00 66 69 6E 64 20 61 20 64 65 63 xes*:.find.a.dec 65 6E 74 20 6A 6F 62 20 74 68 61 74 20 61 63 74 ent.job.that.act 75 61 6C 6C 79 20 70 61 79 73 20 65 6E 6F 75 67 ually.pays.enoug 68 20 74 6F 20 6C 69 76 65 20 6F 6E 20 3A 2D 5C h.to.live.on.:-\ 03 00 ..
Its also neat to look through the output file so you can literally see the physical representation of the binary data that comprises the object. Look at the first line: "0D 00" then our string of data. 0D is hex for 13. There are 13 characters (bytes) in the string "Just some guy". The null byte looks as if VB uses a 2 byte (vb integer) type to hold the string length so 0d 00 is 00 0d held in little endian format. |
From just this much we know that data structures are held in memory as binary data with a header preceeding each component of the structure that details how many bytes are held in the structure. Now look to the beginning of the next string "33 00". &H0033 = 51 decimal..hey guess what there are 51 bytes in the next saved string. so it looks like we have a valid hypothesis from our preliminary data. |
Now if we shift our attention to how it saved the integer value we notice a different setup. For stored integers there is no header. Just the value and an end delimiter (which could either represent the end of the integer value or end of the data structure need more evidence and tests here.) This change is likley due to the way that the C language holds string. I consider VB style strings like a gift from the gods above *bows head in moment of reverance*. In C if you want to save a string...you have to declare an array of characters and have to tell it how many elements are in the array to hold the whole thing! If you tell it wrong then well you are usally overwriting other data as you barge and stomp over other data types. This is called a buffer overflow and there is oodles of infos and warning on it out there. Anyway as i digress... |
We need more tests before we really understand how all the data types are what limitations may be. This is to say that this may not work in every situation. I have yet to really test its boundries. A variable length array for instance can not be directly saved to disk and restored without knowing how many elements the original array contained. Things like preserving data types for variant arrays looks to work, as does things like allowing strings to contain embedded nulls. |
At any rate this is a valid technique and is capable of saving you some
significant coding time. The actual data structure of objects as binary data isnt
somthing VB developers usally have to worry about..but it is a valuable thing to know
and this helps demystify what is actually going on when you pass objects to functions
or create new types. Have fun with it, and if anyone does more any experimenting to
determins the techniques bounds drop me a line and i will include your comments inline
here. If you are intrested in this stop from time to time and see how i and others
progress with it. I have not seen this documented anywhere and i have yet to really
sink my teeth into it an anlysis of it. I can already forsee some nifty uses of this
nto to mention just the sheer visualization factor this brings to my thought and
understanding of what is goign on behind the scenes.
Update: It also appears you can use this same technique to serialize variant arrays to disk. Restored arrays will even maintain their variable types :) Private Sub Form_Load() Dim args(), x() Dim cnt As Byte Dim f As Long, tmp f = FreeFile ReDim args(1 To 3) args(1) = CLng(21) args(2) = CByte(2) args(3) = "21" Open "C:\test.bin" For Binary As f Put f, , CByte(UBound(args)) Put f, , args() Close f Open "C:\test.bin" For Binary As f Get f, , cnt ReDim x(1 To cnt) Get f, , x() Close f tmp = "Recovered elements: " & UBound(x) & vbCrLf For i = 1 To cnt tmp = tmp & "Element: " & i & " Type: " & TypeName(x(i)) & " Value: " & x(i) & vbCrLf Next MsgBox tmp End Sub |