tags:

views:

757

answers:

5

I'd like to store the contents of a data structure, a few arrays, and a dozen or so variables in a file that can be saved and reloaded by my software as well as optionally edited in a text editor by a user reloaded. For the text editing, I need the data to be clearly labeled, like in a good ole .ini file:

AbsMaxVoltage = 17.5

There's a GUI, and one could argue that the user should just load and save and modify from the GUI, but the customer wants to be able to read and modify the data as text.

It's easy enough to write code to save it and reload it (assuming all the labels are in the same place and only the data has changed). With more work (or using some of the INI R/W code that's already out there I could pay attention to the label so if a line gets deleted or moved around the variables still get stuffed correctly, but both of these approaches seem pretty old-school. So I'm interested in how the brightest minds in programming would approach this today (using decade-old VB6 which I have to admit I still love).

Disclaimer: I'm an electrical engineer, not a programmer. This isn't my day job. Well maybe it's a few % of my day job.

Cheers!

+5  A: 

Consider using XML. It's completely standard, many text editors will highlight/manage it properly, every programming language and script language on Earth has good support for reading it, and it handles Unicode perfectly.

For simple name/value pairs as you suggest, it's quite readable. But you have the added advantage that if someday you need something more complex -- e.g. multi-lined values or a list of distinct values -- XML provides natural, easy ways of representing that.

P.S. Here's how to read XML in VB6.

Jason Cohen
Article is a little dated, reference Msxml3.
AnthonyWJones
Yeah but the question is specifically for *VB6* ! Since this is clearly a legacy system, I felt it was appropriate to link to a legacy answer!
Jason Cohen
Msxml3 is hardly cutting edge ;) The article reference 2.6 which can actually lead to all sorts of wierdness. Referencing 3.0 is much cleaner and is present even on quite "legacy" platforms.
AnthonyWJones
Cool, thanks much for the update!
Jason Cohen
lol @claiming a reference for VB6 was a little dated
annakata
Thanks for the suggestion, but I think XML (as some have suggested) is a bit overkill for what I need to do, and more likely that my customers would mess it up so that I couldn't parse it. I saw the irony in asking for a modern solution for a VB6 problem! :-)
Fred Hamilton
+5  A: 

Back in the olden days this class helped me use INI files with my VB6 programs. Take a look.

Jay Riggs
Thanks. And I didn't mean to be insulting with the 'olden days' comments -- I've seen people do really impressive (to me) things in VB6.
Jay Riggs
I certainly wasn't insulted! I'll look into the class you suggested when I get back to work (on vacation this week).
Fred Hamilton
+1  A: 

Would and XML file be acceptable:-

<config>
    <someAppPart
        AbsMaxVoltage="17.5"
        AbsMinVoltage="5.5"
    />
    <someOtherAppPart
        ForegroundColor="Black"
        BackgroundColor="White"
    />
</config>

Its very easy to consume in VB6, you don't need to worry about positioning etc.

The downside is its the user tweaking it can make it unparsable, however thats true if you write your own parser for a config file.

AnthonyWJones
It's the downside you mentioned that worries me (also most of my customers are a bit unsophisticated and will see the nested structure and formatting as a pain). Thanks for the suggestion - I've been listening to the Stack Overflow podcast for months; it's great to see the community in action!
Fred Hamilton
Its not really more nested than a typical .ini although it might be more scary it shouldn't phase someone who wants to tweak something calls AbsMaxVoltage ;)
AnthonyWJones
+2  A: 

Lots of people will recommend XML to you. The problem is XML is still so trendy, some people use it everywhere without really thinking about it.

Like Jeff Atwood said, it's hard for non-programmers to read XML and particularly to edit it. There are too many rules, like escaping special characters and closing the tags in the correct order. Some experts recommend you treat XML as a binary format, not a text format at all.

I recommend using INI files, provided the maximum size limit of 32K is not a problem. I've never reached that limit in many similar situations in my own VB6. INI files are easy for ordinary folk to edit, and it's easy to read and write them from VB6. Just use some of the excellent drop-in code freely available on the web.

  • I'm sure the class Jay Riggs provided in his answer is excellent, because it's from VBAccelerator.
  • I would also recommend this class, because anything by Karl Peterson will be excellent too.

A couple of other points to think about:

  • Have you considered which directory to put the files into?
  • You mentioned "Unicode-friendly" in the question. INI files aren't Unicode, but that doesn't matter in practise. Unless you want to store characters that aren't supported on the current code page - like Chinese on an English computer - an unusual requirement, and one that will cause you other problems in a VB6 program anyway.
  • Legendary Windows guru Raymond Chen described the advantages of XML configuration files over INI files. Many of them rely on the XML file being read-only. The one legitimate advantage is if the data is highly structured - class heirarchies or the like. From your description that doesn't apply.
MarkJ
I mentioned "unicode-friendly" because our software is often used by customers in Asia and we sometimes see unexpected incompatibilities that usually boil down to unicode (len() function failing or reporting the wrong value, etc.). Thanks for the in-depth response.
Fred Hamilton
Our software is used by customers in China - the INI files have been working fine. There are some gotchas in VB6 though. Michael Kaplan's book on Internationalization in VB6 is very useful, especially if you translate the user interface. see http://www.i18nwithvb.com/
MarkJ
I see you're based in the US. If you use characters from the range Chr$(128)-Chr$(255) in hard-coded strings or elsewhere, they'll give you problems in Asia. The characters from the range chr$(1) - chr$(127) are supported on all code pages.
MarkJ
A: 

If we can assume your saved settings are simply a set of name/value pairs without a two-level hierarchy requirement (i.e. INI "Keys" within "Sections") you might just persist them as such:

AbsMaxVoltage=17.5
AbsMinVoltage=5.5

For writing the persistence format this is a case where you might consider the FSO, since the access volume is low anyway. The FSO can handle read/writing Unicode text files.

I think I'd do something like read lines and parse them using a Split() on "=" specifying just 2 parts (thus allowing "=" within values as well). For loading these I'd store them into a simple Class instance where the Class has two properties (Name and Value) and add each one to a Collection using Name as the Key. Make Value the default property if desired.

Maybe even implement some form of comment text line too using a generated sequence-numbered special Name value stored as say Name="%1" Value="comment text" with generated unique Names to avoid Collection Key collisions. Blank lines might be similarly preserved.

Then persisting as necessary means simply using a For Each on the Collection and using the FSO to write Name=Value out to disk.

To simulate a hierarchy you could simply use Names like:

%Comment: somAppPart settings
someAppPart.AbsMaxVoltage=17.5
someAppPart.AbsMinVoltage=5.5

%someOtherPart settings
someOtherAppPart.ForegroundColor=Black
someOtherAppPart.BackgroundColor=White

The parsing is cheap, so any probing of the Collection might be preceded by a full reparse (as the INI API calls do). Any changing of values in the program might do a full rewrite to disk (like the INI API calls do).

Some of this can be automated by just wrapping the Collection with some logic in another Class. The result could be syntax like:

Settings("someOtherAppPart", "ForegroundColor") = "Red"

aka

Settings.Value("someOtherAppPart", "ForegroundColor") = "Red"

This would reload the Collection, then probe the Collection for an Item keyed "someOtherAppPart.ForegroundColor" and create it or set its Value to "Red" and then flush the Collection to disk. Or you might eschew frequent rewriting and use distinct Load and Save methods.

Make it as simple or fancy as desired.

In any case, the result is a text file users can hack at with Notepad. The only reason for the FSO is to have an easy way of read/writing Unicode text. One could also screw around with Byte array I/O and explicit conversions (array to String) and line level parsing as required to avoid the FSO. If so just don't forget about the UTF-16LE BOM.

Bob