December 19, 2014
Hot Topics:

C++ Tip: Versioning Serialized Files with Managed C++

  • May 26, 2004
  • By Tom Archer
  • Send Email »
  • More Articles »

Testing the Example

  1. At this point, the class is complete. Now, you need only write two very simple functions to serialize this class's members. As I mentioned in previous articles, I personally implement these methods as static methods—called Open and Save—in a helper class. For those of you accustomed to MFC serialization and having the class serialize itself, that unfortunately won't work with .NET serialization because the Formatter object does the actual serialization and instantiates a new object during the read. This is different from MFC, where the class can simply open the CArchive object and perform its own insertion and extraction. Hence, the need for another class—or the client code—to make the calls to perform the serialization:
  2. __gc class YourClassSerializer
    {
    public:
      static YourClass* Open(String* fileName)
      {
        YourClass* yc = NULL;
    
        FileStream* stream = new FileStream(fileName,
                                            FileMode::Open,
                                            FileAccess::Read);
        BinaryFormatter* formatter = new BinaryFormatter();
        yc = static_cast<YourClass*>
             (formatter->Deserialize(stream));
        stream->Close();
    
        return yc;
      }
    
      static void Save(YourClass* yc, String* fileName)
      {
        FileStream* stream = new FileStream(fileName,
                                            FileMode::Create,
                                            FileAccess::Write);
        BinaryFormatter* formatter = new BinaryFormatter(); 
        formatter->Serialize(stream, yc); 
        stream->Close();
      }
    };
    
  3. Finally, you need only call the two static helper class functions to serialize your files. Note the reference to the Exception::InnerException object. This is due to the fact that when an object being serialized throws an exception, the Formatter object will catch that exception and wrap it in its own exception that is then thrown.

    One way to test this code is to create and save a file with a given version (fileVersion member) such as 1.10, change the fileVersion member to 1.20, and then open the "1.10" file. You'll see that your code automatically converts the "1.10" file to a "1.20" file when you save. Conversely, if you save the file as a "1.20" version, modify the fileVersion to "1.10", and then try to open the file, the code will throw an exception as designed:

    try
    {
      YourClass* yc;
    
      // create and save test file
      yc = new YourClass();
      YourClassSerializer::Save(yc, S"test.yc");
    
      // open existing file
      // yc = static_cast<YourClass*>
              (YourClassSerializer::Open(S"test.yc"));
    
      // save current file
      // YourClassSerializer::Save(yc, S"test.yc");
    }
    catch(Exception* e)
    {
      Console::WriteLine(e->Message);
      if (e->InnerException)
        Console::WriteLine(e->InnerException->Message);
    }
    

Additional Notes

In the YourClass example (and as I mentioned in the description of the GetObjectData method), the code automatically converts older file formats to the current format. You've probably seen many applications that—upon opening an older-formatted file—ask you whether or not you want to convert the file. Here's an easy way to implement that:

  1. Define a property in the class called something like AutoConvertEarlierFormats, initializing it to false.
  2. In situations where the file format is older than the latest version, check to see whether the AutoConvertEarlierFormats property is true. If it is, initialize the members not previously saved according to your application's needs. If the value is false, throw an exception that the client code knows how to handle that indicates that the file format is older but can be converted.
  3. The client code then asks the user whether or not he or she wants to convert the file.
  4. If the user does, simply set the AutoConvertEarlierFormats property to true and retry the open operation by which the file should be successfully opened and automatically saved to the current file-format version when the file is serialized.

Download the Code

To download the accompanying source code for this tip, click here.

About the Author

The founder of the Archer Consulting Group (ACG), Tom Archer has been the project lead on three award-winning applications and is a best-selling author of 10 programming books as well as countless magazine and online articles.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel