Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Rhinorhino on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Saving to binary files

Status
Not open for further replies.

TheVampire

Programmer
Joined
May 1, 2002
Messages
828
Location
US
I know you can save an array to a binary file, but will this also work for collections?
 
I have done this in the past with collections of my own objects (VB classes).

The key to this is that instead of using individual, member variables for storing the values of your class properties, use a single UDT with multiple elements. Then, you can save the entire UDT to a file with the PUT command. Make it even easier by adding WriteFile and ReadFile methods to your class that write the UDT to an open file in binary and read the next UDT from an open file in binary and you are well on your way.

The following article describes this approach pretty well.


Good luck.
Tom Rogers
TJRTech, Inc
 
Time is short, so this may seem a little cryptic - but you can persist classes (serialize them and save them as binary) through the PropertyBag object. Check out the documentation.
 
Well, my problem is that I have collections ( and arrays ) that contain many object references. When I try to use PUT into a binary file, it tells me I can't PUT an object reference or a UDT that contains one. When I try to write to the propertybag, it tells me that I can't write an object because it does not support persistence.

Any ideas?
 
Right, TheVampire, if using Put$ then you can only use a raw UDT, not a UDT that contains an object. And, you can't PUT an object.

The example that I stated is for collections of objects. The collection would hold a single type of object that you have written. In the object (.cls) source, you would have a UDT for storing the member variable values. And, that UDT would have to have fixed strings, or other fixed var types (no objects). This simply provides a fixed sized UDT for storing all your property values. And, since it's a UDT of fixed size, it can be written to and read from a binary file easily.

That's the limitations you deal with.

As for propertybag, I am not sure as I haven't used them.

Tom
 
It's funny that this thread should pop back up now. I just finished writing and debugging ( I think... ) the process to save all of my ap's data to a binary file.

What I was trying to do, was to write several arrays and UDT's ( which contain information about controls that have been created at run time, plus a bunch of other data ), all of which could vary in size from one point in time to another, to a single binary file.

I wanted to assign all of these things to a variant, cause you can assign an array to it, and then write the variant to a binary file.

Well, my problem was that:

1: I had object references all over the place in these arrays and collections and UDTs, and you can't PUT a reference. ( Because, once I thought about it, each ref is just a pointer to a memory location, and it won't be the same the next time the app runs ).

2: You can't assign an array of UDT's to a variant unless you declare the UDT in a public object module ( class module or other type of object module ). Which is more work than I wanted to get into at the moment.

Well, what I did was convert all of my object ref's to strings before saving. After I read the data back, I use a Select Case structure to recreate my ref's.

Then, I changed all of my UDTs over to arrays instead, and used variants to make an "Array of arrays", assigned this to a variant, used a simple put statement to write that to the file, and by gosh it worked! :)

Robert
 
Wow...

A few questions about what you did:

1) You say you "converted your object references to strings", can you explain what you did? For instance, did you concatenate all your object property values into a long string, say with some type of seperator between property values?

2) Do you "prepend" some type of object descriptor, or name at the head of the strings described above? I ask because I assume this is where the SELECT comes into play on reading???

3) When you sayd you "...used a variant to make an array of arrays", was this a two dimensional array of the strings from above? Why an array of arrays? Is it because all the objects of a single type are in one array, and thus you have several such arrays?

4) Lastly, were your strings fixed size?

Tom,
TJRTech, Inc.
 
Well, First let me give a little background on what my project does.

My company makes security systems. These systems have many different "modules" that perform different functions. One module is used as a entry point for access codes, another is used to connect alarm contacts, and so on. These modules can be connected up in many custom ways, but there are rules about how they can be connected. Along with the hardware component of our system, there is a custom software component that is generated based on how the hardware modules are connected together.

What my project does, is allows a user to "lay out" the hardware, makes sure that they follow the rules on the layout, and generates the custom software needed for that specific layout. Along the way it also allows them to print out a picture of the layout and connections ( a customized schematic diagram ), and wiring instructions for the system, and of course, save any layouts they have generated to a file.



1: As for the object references, what I have in my project are 16 different objects that represent the hardware "modules" of the security system. These are actually controls ( Command buttons ) that I create at run time and place on a worksheet ( a picture box ) that the user can scroll around. By dragging and dropping the buttons, they connect the various modules together ( lines are drawn on the picturebox to show these connections graphically ) These controls are pointed at by several arrays in my project.

What I did was take the name of the control, and its index, and make a string ( Control.Name & " " & Control.Index ) and placed this in the array that I wanted to save.

When I load the information back in, I loop through the array and look at each item. If it's a number I handle it separately, and if it's a string I use the Split function to extract the first whole word from the string. I use the SELECT structure to see if it matches one of my 16 possible control names, and if it does I recreate the reference with a SET statement at that point. If it does not match one of my control names, I know it's a regular string and just use it as normal.

2: All I used to ID the object reference was the name of the control.

3: I have a lot of arrays that are being used to hold the data on how the different modules are connected together, and the data for the custom software setup. This is pretty much the structure of these arrays:

23 two dimension arrays for software setups and control properties( SaveArrays() ).

2 one dimension arrays for storing objects held in two collections. ( SaveLineArray() and SaveControlArray() ).

1 one dimension array for saving all of my Index 0 control .tag properties. ( SaveTags() )

Plus a string ( DWZVersion ) that just saves the version of the data file, if I change the way the data is stored later.

I used an intermediate variant ( Item ) to store each of these arrays into a single dimension array.

' move the items into "BigSaveArray"
BigSaveArray(0) = DWZVersion
Item = SaveControlArray()
BigSaveArray(1) = Item
Item = SaveLineArray()
BigSaveArray(2) = Item
Item = SaveTags()
BigSaveArray(3) = Item
Item = SaveArrays()
BigSaveArray(4) = Item

'Then I move the entire "BigSaveArray" into the variant

Item = BigSaveArray()

FNum = FreeFile()

Open CD.FileName For Binary As #FNum
Put #FNum, , Item
Close #FNum


This writes the entire array to a file, and automatically stores all of the information that VB needs as far as the length of the data.

The reverse of the process reads a variant back out of the file, assigns it to the array ( which is a dynamic array ), and then I just pull the individual arrays back out of the "BigSaveArray".


Open CD.FileName For Binary As #FNum
Get #FNum, 1, Item
BigSaveArray() = Item
Close #FNum

' pull the other arrays out of "BigSaveArray"
DWZVersion = BigSaveArray(0)

Item = BigSaveArray(1)
SaveControlArray() = Item

Item = BigSaveArray(2)
SaveLineArray() = Item

Item = BigSaveArray(3)
SaveTags() = Item

Item = BigSaveArray(4)
SaveArrays() = Item

Then I pull the data as needed out of the arrays, reload all of the controls onto the worksheet, set their properties ( Left, top, height, width, caption, and a integer that points to an index in a ImageList control, to tell me what picture the control should have on it ), reset all of my references and recreate my collections.


And that's pretty much it. None of my strings are fixed size by the way.

Robert [peace]
 
Cool...I didn't know that VB could save arrays like that via PUT. I guess it shouldn't have surprised me, though, given that an array, like a variant is just another automatable type. I am going to try this and then inspect the data file with a hex editor. I suspect I will see header info much like a variant (data type, size info, offsets, etc).

Tom
TJRTech, Inc.
 
I didn't know it either, until I got my new reference book that Foada recommended to me: Programming MS Visual Basic 6.0 by Francesco Balena.

When I get a free moment, I'm going to write a review and post it here. This book has already paid for itself and more!

Robert
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top