Reputation: 25969
This happens only sometimes, but makes my files unreadable. The problem is that the DataContractSerializer adds a couple of >>> at the end of the XML files when serializing. Making them useless when trying to deserialize. Has anyone had this problem? Example:
<SomeObject xmlns="someNamespace">
</SomeObject>>>
Thanks.
Edit:
Actually no, that's not the problem. The file is fine this time, this is what it looks like:
<FavoriteClubManager xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TicketingWP7.Preferences">
<FavoriteClubs xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:KeyValueOfstringboolean>
<d2p1:Key>XXX</d2p1:Key>
<d2p1:Value>true</d2p1:Value>
</d2p1:KeyValueOfstringboolean>
</FavoriteClubs>
</FavoriteClubManager>
And this is the error I get when trying to deserialize it:
"There was an error deserializing the object of type TicketingWP7.Preferences.FavoriteClubManager. Root element is missing."
But I don't see anything wrong with the file.
Code
Saving:
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
try
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Create, file))
{
DataContractSerializer serializer = new DataContractSerializer(typeof(FavoriteClubManager));
serializer.WriteObject(stream, this);
}
}
catch (Exception ex)
{
MessageBox.Show("There was an error saving your favorite clubs. " + ex.Message);
}
}
Loading:
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
if (file.FileExists(_fileName))
{
try
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Open, file))
{
DataContractSerializer serializer = new DataContractSerializer(typeof(FavoriteClubManager));
FavoriteClubManager temp = serializer.ReadObject(stream) as FavoriteClubManager;
stream.Close();
}
_isLoaded = true;
}
catch (Exception ex)
{
MessageBox.Show("There was an error loading your favorite clubs. " + ex.Message);
}
}
}
Upvotes: 1
Views: 2194
Reputation: 25969
Solved it. Pretty much cheated on it. I basically read the XML document with an XDocument, get the reader with XDocument.CreateReader() and pass the reader to the DataContractSerializer. That did the trick, I know it's not very elegant, but it's a solution. Hopefully I'll come up with a better solution in the future. For now, here's the code:
private bool Load()
{
if (!_isLoaded)
{
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
if (file.FileExists(_fileName))
{
string text = string.Empty;
try
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Open, file))
{
if (stream.Length > 0)
{
XDocument document = GetXDocument(stream);
DataContractSerializer serializer = new DataContractSerializer(typeof(ClubManager));
ClubManager temp = serializer.ReadObject(document.CreateReader()) as ClubManager;
stream.Close();
}
}
_isLoaded = true;
}
catch (Exception ex)
{
MessageBox.Show("There was an error loading your favorite clubs. " + ex.Message);
}
}
}
}
return _isLoaded;
}
private XDocument GetXDocument(IsolatedStorageFileStream stream)
{
// read the file to find errors
string documentText = ReadBytes(stream);
return XDocument.Parse(documentText);
}
private static string ReadBytes(IsolatedStorageFileStream stream)
{
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
string normal = string.Empty;
string hex = BitConverter.ToString(buffer).Replace("-", "");
while (hex.Length > 0)
{
// Use ToChar() to convert each ASCII value (two hex digits) to the actual character
normal += System.Convert.ToChar(System.Convert.ToUInt32(hex.Substring(0, 2), 16)).ToString();
// Remove from the hex object the converted value
hex = hex.Substring(2, hex.Length - 2);
}
return normal;
}
Thanks!
Upvotes: 0
Reputation: 65566
Is the problem actually this:
If that's the flow to recreate the issue, I suspect that subsequent saved seializations are of a slightly smaller object and so create a serialized string which is smaller than that written previously.
When the later string is saved it is written on top of the previously saved string with the end of the old string being left there still.
The solution is to make sure that the existing file is deleted or it's contents removed before saving the new contents.
I had a similar issue previously and it was a pain to uncover.
BTW. You may also want to reconsider your serialization strategy with regard to performance. Take a look at this blog post by Kevin Marshall for more information.
Upvotes: 4