I've been reading about how to write data to disk using the System.IO.Packaging namespace in .NET 3.0. This lets you create "packages" which are essentially zip files. You can store whatever you like in 'em, and it all gets neatly wrapped up into a single file.

Comicster right now simply saves its DataSet (using the WriteXml method) through a CompressionStream to disk. That works quite well, and compresses very nicely (since it's XML). The overheads of using a DataSet do make the file slightly bigger than it needs to be, but my collection of over 700 comics clocks in at around 500kB, which is acceptable to me.

With the new .NET 3.0 version of Comicster that I've been toying with, I've more or less abandoned the DataSet, and instead I'm using raw objects. To stream them out to disk I'm using an XmlWriter and manually writing the bits that I want into a FileStream. Uncompressed, the resulting XML file is almost 2MB. Running this through a CompressionStream brings it back down to 290kB - well below the size of the DataSet's compressed file.

Using the System.IO.Packaging.Package class is only a few extra lines of code, and the resulting file is still only 291kB - an acceptable trade-off when you consider that I'm adhering to the zip file standard.

Basically a "package" is made up of "parts" (basically representing the files within the zip). Each "part" has a "GetStream()" method, and you can use your existing code to read to and write from that stream, so it's really easy to shoehorn into legacy code. Here's mine:

public static void Save(Collection collection, string filename) 
{
    string ext = Path.GetExtension(filename).ToLower();
    if (ext == ".cmxx")
    {
        using (var pack = ZipPackage.Open(filename, FileMode.Create))
        {
            var part = pack.CreatePart(_collectionUri,
                System.Net.Mime.MediaTypeNames.Text.Xml, 
                CompressionOption.Maximum);
            Save(collection, part.GetStream());
            pack.CreateRelationship(part.Uri, TargetMode.Internal, 
                _packageRelationshipType); 
        } 
    } 
    else // just save it as raw XML  
    {
        using (var fileStream = new FileStream(filename, FileMode.Create))
        {
            Save(collection, fileStream);
        }
    }
} 

Pretty cool, huh? All I've done is created a ZipPackage, created a single PackagePart within it and then used that part's GetStream method to give me a stream to save my collection to (using the Save method that I had already defined). Note that you can specify on a per-part basis what sort of compression you want to use. This is handy if you're saving already-compressed data (like jpegs) into the package.

The "_collectionUri" identifier is just a constant of type Uri with a value of "/Content/Collection.xml". That tells the zip file where to store that particular stream in the zip.

Considering how easy this, it's a no-brainer to use it if you're creating a .NET 3.0 application that needs to persist data to disk.