If you’re worked on any sort of application that had to transfer data between applications, you have probably had to serialize data. Serialization is the process of converting objects to a collection of bytes that can be interpreted by the application receiving the data. The application receiving the data can be another application on the same computer, but more often is an application on a remote computer. You can get a more formal definition here. I’m going to talk about serialization as it applies specifically to the .NET 2.0 Framework.

The framework has support for serialization built in with the BinaryFormatter and SoapFormatter classes. I’m going to start with the BinaryFormatter class. The first thing I need to point about about using a BinaryFormatter is that it’s only readable by applications written in the .NET Framework. Another item worth mentioning is that objects formatted using the BinaryFormatter have a better chance of being blocked by a firewall, so if you are transferring data to remote computers, this is something to consider.

Let’s get started with an example. Let’s say we want to build an application to track statistics for our baseball league. We have a laptop that we will bring to the game, and a server at home that will hold all of the data, so there will be 2 parts to our application. The basic idea of our application is to collect the game data using our laptop, and move it to our server when we get home. Serialization is one way to accomplish this. Here is an example player class we could use: (in C#)


// Adding the Serializable attribute to our class
// allows us to serialize it
[Serializable]
public class Player
{
/*-------------------------------------------------------------*/
// Private data members.
private int _atBats;
private int _hits;
private int _homeRuns;
private int _rbi;
private int _runs;
private string _name;
/*-------------------------------------------------------------*/
// These are our public properties.
public int AtBats
{
get { return _atBats; }
set { _atBats = value; }
}
/*-------------------------------------------------------------*/
public int Hits
{
get { return _hits; }
set { _hits = value; }
}
/*-------------------------------------------------------------*/
public int HomeRuns
{
get { return _homeRuns; }
set { _homeRuns = value; }
}
/*-------------------------------------------------------------*/
public int RBI
{
get { return _rbi; }
set { _rbi = value; }
}
/*-------------------------------------------------------------*/
public int Runs
{
get { return _runs; }
set { _runs = value; }
}
/*-------------------------------------------------------------*/
public string Name
{
get { return _name; }
set { _name = value; }
}
/*-------------------------------------------------------------*/
// Constructor
public Player()
{

}
/*-------------------------------------------------------------*/
}



All we had to do to be able to serialize our class is to put the [Serializable] attribute above it. It doesn’t get much easier than that! Now lets say our application has a List<Player> declared. We decide that we want to serialize a separate file for each player on our list. We could also just serialize the whole list, but we’ll do it this way instead. I have to throw out my standard disclaimer…..I’m going light on the error handling to make the example more clear.


string fileName;
// This is our list of players on the team.
List teamList = new List();

// Assume that our application has compiled game stats
// for each player in the list and that we are ready
// to serialize the data. For example purposes, I'll
// just hard code a few players and add them to the list.
Player p1 = new Player();
p1.AtBats = 4;
p1.Hits = 1;
p1.HomeRuns = 0;
p1.RBI = 2;
p1.Runs = 1;
p1.Name = "John Doe";
teamList.Add(p1);

Player p2 = new Player();
p2.AtBats = 4;
p2.Hits = 3;
p2.HomeRuns = 1;
p2.RBI = 2;
p2.Runs = 1;
p2.Name = "Jimmy Smith";
teamList.Add(p2);

// Declare our formatter and filestream;
BinaryFormatter formatter;
FileStream fStream;

// Loop through each player and serialize the data to a file.
foreach (Player currentPlayer in teamList)
{
// I'm going to just use their name for the filename,
// replacing spaces with underscores.
// In reality we would check for invalid characters
// here also, etc.
fileName = currentPlayer.Name.Replace(' ', '_') + ".dat";

// This creates our data file.
fStream = new FileStream(fileName, FileMode.Create);

// Create our binary formatter object.
formatter = new BinaryFormatter();

// Serialize our player data.
formatter.Serialize(fStream, currentPlayer);

// Close our data file.
fStream.Close();
}



That’s it. We now have our 2 player objects serialized into separate files that we can move to our PC and deserialize. One thing I should point out, using a BinaryFormatter requires the System.Runtime.Serialization.Formatters.Binary namespace to be included in your project. If you open up one of the files that we generated in Notepad, it will look like a bunch of gibberish, but that’s OK, we’ll be able to read it just fine. Here is an example of some code that would read these files on our PC at home. I’m assuming the files were dropped into a directory called import that was in the same directory as our application. This function is one way to read these files and put them back into List form.


public List Deserialize()
{
// Our function will return a list of player objects.
List playerList = new List();
Player currentPlayer;
string importPath, fileName;

// Declare our FileStream and BinaryFormatter
FileStream fStream;
BinaryFormatter formatter;

// Set up the import directory path.
importPath = Directory.GetCurrentDirectory()
+ Path.DirectorySeparatorChar + "import";

DirectoryInfo importDirectory = new DirectoryInfo(importPath);
foreach (FileInfo file in importDirectory.GetFiles())
{
// Set up the correct filename.
fileName = importPath + Path.DirectorySeparatorChar
+ file.Name;

// Open our data file for reading.
fStream = new FileStream(fileName, FileMode.Open);

// Create our binary formatter object.
formatter = new BinaryFormatter();

// Deserialize our data stream into a Player object.
currentPlayer = (Player)formatter.Deserialize(fStream);

// Close our file stream.
fStream.Close();

// Add the player to our list.
playerList.Add(currentPlayer);
}

// Return the list.
return playerList;
}



Another type of serialization uses the SoapFormatter class. The syntax of using this is almost identical to using the BinaryFormatter class since the both implement the IRemotingFormatter interface, so I won’t get into specific examples, but I will point out a few things that may be worth knowing. This class is less efficient than the BinaryFormatter class, but it is a better choice if there are firewall concerns. The reason it is less efficient is because it is intended to be used with web services. Serialization with SOAP can make the serialized objects 3 or 4 times as big as the same object serialized with a BinaryFormatter. Keep in mind though that something serialized with a SoapFormatter can be read by applications on different platform because of the SOAP standard, so that is something to consider.

That wraps up the first article on serialization. My next one will deal with things such as choosing fields to skip in the serialization process, choosing optional fields in an object, as well as XML specific formatting via libraries in the System.Xml.Serialization namespace.

kick it on DotNetKicks.com