2

Alright, The following code I've had in production for over a year with no changes. It has been working quite well. Within the past month more then a handful machines report that the xml documents are completely empty. They do not even contain a xml header . I cannot duplicate the files suddenly being empty, nor can i suggest a way for it to happen. I am hoping someone has had a similar issue that they solved.

Most of the machine that have been using this code have been using it for about a year, if not more. The empty files used to have data and lists in them.The files do not serialize at the same time. The save / serialize one after the other before the program exits.

My questions: is it possible for the code below to create an empty file? What else would cause them to be suddenly empty? Has anyone else had issues with XML-serializer in the past month? (This problem has only happened in the past month on builds that have been stable for 3+ months.)

If you have questions or i missing something ask please. There also is a wide variety of types that i serialize... so if you can imagine it I probably have something similar that gets serialized.

 public class BackEnd<T> {
 public string FileSaveLocation = "this gets set on startup";
 public bool DisabledSerial;
 public virtual void BeforeDeserialize() { }
 public virtual void BeforeSerialize() { }
 public virtual void OnSuccessfulSerialize() { }
 protected virtual void OnSuccessfulDeserialize(ListBackEnd<T> tmpList) { }
 protected virtual void OnDeserialize(ListBackEnd<T> tmpList) { }

 public virtual void serialize()
    {
        if (DisabledSerial)
            return;
        try
        {
            BeforeSerialize();

            using (TextWriter textWrite = new StreamWriter(FileSaveLocation))
            {
                (new XmlSerializer(this.GetType())).Serialize(textWrite, this);
                Debug.WriteLine(" [S]");
                textWrite.Close();
            }
            OnSuccessfulSerialize();
        }
        catch (Exception e)
        {
            Static.Backup.XmlFile(FileSaveLocation);
            Log.ErrorCatch(e,
                "xml",
                "serialize - " + typeof(T) + " - " + (new FileInfo(FileSaveLocation)).Name);
        }

    }

    public virtual object deserialize(TextReader reader)
    {
        if (this.DisabledSerial)
            return false;


        ListBackEnd<T> tmp = null;


        this.BeforeDeserialize();

        if (reader == null && !File.Exists(this.FileSaveLocation))
        {
            Log.Write(Family.Error,
                "xml",
                "deserialize - " + this.GetType() + " - file not found. " + (new FileInfo(FileSaveLocation)).Name);
        }
        else
        {
            try
            {
                using (TextReader textRead = ((reader == null) ? new StreamReader(this.FileSaveLocation) : reader))
                {
                    tmp = (ListBackEnd<T>)this.get_serializer().Deserialize(textRead);
                    Debug.WriteLine(" [D]");
                    textRead.Close();
                }
                OnSuccessfulDeserialize(tmp);

                if (tmp != null)
                {
                    this._Items = tmp._Items;
                    this.AutoIncrementSeed = tmp.AutoIncrementSeed;
                    if (this._Items.Count > this.AutoIncrementSeed && this._Items[0] is ItemStorage)
                        this.AutoIncrementSeed = this._Items.Max(item => (item as ItemStorage).Key);
                }
            }
            catch (Exception e)
            {
                // this only copies the file
                Static.Backup.XmlFile(FileSaveLocation);
                // this only logs the exception
                Log.ErrorCatch(e,
                    "xml",
                    "deserialize - " + typeof(T) + " - " + (new FileInfo(FileSaveLocation)).Name);
            }
        }
        //{ Log.ErrorCatch(e, "xml", "deserialize" + this.GetType() + " - " + this.FileSaveLocation); }

        OnDeserialize(tmp);

        tmp = null;

        return (_Items.Count > 0);
    }
}
Gauthier
  • 1,251
  • 10
  • 25

2 Answers2

7

We've encountered this problem several times at $WORK, with the symptom being an empty file of the correct size but filled with zero bytes.

The solution we found was to set the WriteThrough value on the FileStream:

using (Stream file = new FileStream(settingTemp, FileMode.Create,
                                   FileAccess.Write, FileShare.None,
                                   0x1000, FileOptions.WriteThrough))
{
   using (StreamWriter sw = new StreamWriter(file))
   {
      ...
   }
}
Malcolm
  • 1,239
  • 1
  • 14
  • 25
3

The only reason I can think that this would happen is that this line:

(new XmlSerializer(this.GetType())).Serialize(textWrite, this);

throws an exception and the textwriter is created and disposed without ever having anything written to it. I'd look at your log for errors.

What does

Static.Backup.XmlFile(FileSaveLocation);

do?

Dustin Hodges
  • 4,110
  • 3
  • 26
  • 41
  • I'll take that. It never occured to me that exceptions inside a the using statement would empty the file like that. Theres other things going on well. Greatly appreciated Dustin. – Gauthier Dec 07 '10 at 19:34
  • It just makes a copy of the file. If for some reason I didn't add optional field attributes properly it saves the original. – Gauthier Dec 08 '10 at 03:20