Bedford
Bedford

Reputation: 1186

XML serialization results in a file full of null characters

I'm serializing an object (of class Car) and saving it as an xml file. However sometimes (very rare event, I can't replicate it) I get a file that contains only null characters (characters with 0 ASCII code), even though the file size is correct.

public void SaveCar(Car car)
{
    var serializer = new XmlSerializer(typeof(Car));
    using (var stream = new MemoryStream())
    {
        serializer.Serialize(stream, car);
        byte[] binaryCar = stream.ToArray();
        FileHelper.WriteAllBytes(@"C:\car.xml", binaryCar);
    }
}

FileHelper.WriteAllBytes is the same as System.IO.File.WriteAllBytes, except that it creates the parent directory if it doesn't exist.

public static class FileHelper
{
    public static void WriteAllBytes(string path, byte[] bytes)
    {
        CreateParentDirectoryForPathIfDoesntExist(path);
        File.WriteAllBytes(path, bytes);
    }

    public static void CreateParentDirectoryForPathIfDoesntExist(string filePath)
    {
        var file = new FileInfo(filePath);
        if (file.Exists)
        {
            return;
        }

        if (file.Directory != null && !file.Directory.Exists)
        {
            Directory.CreateDirectory(file.Directory.FullName);
        }
    }
}

Any idea what can cause this? Encoding issues?

Upvotes: 1

Views: 1358

Answers (1)

recineshto
recineshto

Reputation: 128

Your 'SaveCar' method seams to work nicely, but I you want you can use following implementation

public class XmlCar {
    public static readonly Encoding Utf8Encoding = Encoding.UTF8;
    public static readonly XmlSerializer CarSerializer = new XmlSerializer(typeof(Car));
    public static Car Load(string path) {
        using (var stream = new StreamReader(path, Utf8Encoding, false)) {
            using (var reader = XmlReader.Create(stream)) {
                return (Car)CarSerializer.Deserialize(reader);
            }
        }
    }
    public static void Save(string path, Car instance) {
        using (var stream = new StreamWriter(path, false, Utf8Encoding)) {
            using (var writer = XmlWriter.Create(stream)) {
                CarSerializer.Serialize(writer, instance);
            }
        }
    }
}

The biggest difference from yours example is that serializer-instance is created once and UTF8 encoding is forced.

Your method was tried with following classes

[XmlRoot]
public class Car {
    [XmlAttribute]
    public string Model { get; set; }
    [XmlAttribute]
    public string Plate { get; set; }
    [XmlArray]
    [XmlArrayItem]
    public List<Part> Parts { get; set; }
}
[XmlRoot]
public class Part {
    [XmlAttribute]
    public string Type { get; set; }
    [XmlAttribute]
    public string Code { get; set; }
    [XmlAttribute]
    public int Quantity { get; set; }
}

Please note that this sample is derived from samples found on this site.

Yours method was changed a bit to accommodate some control over file name.

    public static void SaveCar(Car car, int i)
    {
        var serializer = new XmlSerializer(typeof(Car));
        using (var stream = new MemoryStream())
        {
            serializer.Serialize(stream, car);
            byte[] binaryCar = stream.ToArray();
            File.WriteAllBytes("car"+ i + ".xml", binaryCar);
        }
    }

Method was tested with following function

    static void Main(string[] args) {

        var random = new Random();
        var cars = new List<Car>();

        for (var c = 0; c < 10; c++) {
            var car = new Car() {
                Model = Guid.NewGuid().ToString(),
                Plate = (random.Next(500) + 500).ToString(),
                Parts = new List<Part>()
            };
            for (var p = 0; p < 100; p++) {
                car.Parts.Add(new Part() {
                    Type = Guid.NewGuid().ToString(),
                    Code = (random.Next(500) + 1500).ToString(),
                    Quantity = random.Next(100) + 1
                });
            }
            SaveCar(car, c);
            cars.Add(XmlCar.Load("car" + c + ".xml"));
        }
    }

Upvotes: 1

Related Questions