Hugo Gonçalves
Hugo Gonçalves

Reputation: 61

C# DataTable Binary Serialization

Quick noob question which is really bothering me, I am serializing a DataTable array however when deserializing it back an exception is thrown for 'The input stream is not a valid binary format'

Serialization

    public static bool saveToFile(DataTable[] NW, string path)
    {
        try
        {
            using (var stream = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream,NW);
                stream.Close();
                File.WriteAllBytes(path,stream.ToArray());
            }
            return true;
        }
        catch(Exception ex)
        {
            MessageBox.Show("ERROR" + Environment.NewLine + ex.Message);
            return false;
        }
    }

Deserialization

public static DataTable[] loadFromFile(string path)
    {
        try
        {
            byte[] buffer = File.ReadAllBytes(path);
            var stream = new MemoryStream(buffer);
            IFormatter formatter = new BinaryFormatter();
            return (DataTable[])formatter.Deserialize(stream);
        }
        catch(Exception ex)
        {
            MessageBox.Show("ERROR" + Environment.NewLine + ex.Message);
            return null;
        }
    }

I've also tried it without the MemoryStream and used instead the File Stream returned by File.Open(string path, FileMode.Create/Open)

Also, just before writing it to the file this is the look of the byte array:

M

When reading it

:e

It looks like as it didn't really wrote everything to the file?

Upvotes: 1

Views: 6696

Answers (2)

Martin.Martinsson
Martin.Martinsson

Reputation: 2154

    public static class DataTableSerializer
{
    public static byte[] FastSerialize(this DataTable tbl, out string tableSchema)
    {
        var tableItems = new object[tbl.Rows.Count][];
        for (var rowIndex = 0; rowIndex < tbl.Rows.Count; rowIndex++)
            tableItems[rowIndex] = tbl.Rows[rowIndex].ItemArray;

        var serializationFormatter = new BinaryFormatter();

        using (var buffer = new MemoryStream())
        {
            serializationFormatter.Serialize(buffer, tableItems);

            var tableSchemaBuilder = new StringBuilder();
            tbl.WriteXmlSchema(new StringWriter(tableSchemaBuilder));
            tableSchema = tableSchemaBuilder.ToString();

            return buffer.ToArray();
        }
    }

    public static DataTable FastDeserialize(byte[] serializedData, string tableSchema)
    {
        var table = new DataTable();
        table.ReadXmlSchema(new StringReader(tableSchema));

        var serializationFormatter = new BinaryFormatter();
        object[][] itemArrayForRows;

        using (var buffer = new MemoryStream(serializedData))
        {
            itemArrayForRows = (object[][]) serializationFormatter.Deserialize(buffer);
        }

        table.MinimumCapacity = itemArrayForRows.Length;
        table.BeginLoadData();

        for (var index = 0; index < itemArrayForRows.Length; index++)
        {
            var t = itemArrayForRows[index];
            table.Rows.Add(t);
        }

        table.EndLoadData();

        return table;
    }
}

Upvotes: 2

Hugo Gon&#231;alves
Hugo Gon&#231;alves

Reputation: 61

Following Lu Henry comment, It is actually working by moving the tables to a dataset and then write it.

    public static bool saveToFile(DataTable[] NW, string path)
    {

        try
        {
            var NWDS = new DataSet();
            foreach (DataTable dt in NW) {
                NWDS.Tables.Add(dt.Copy());
            }
            NWDS.WriteXml(File.Create(path));
            return true;
        }
        catch(Exception ex)
        {
            MessageBox.Show("ERROR" + Environment.NewLine + ex.Message);
            return false;
        }
    }


    public static DataTable[] loadFromFile(string path)
    {
        try
        {
            var NWDS = new DataSet();
            NWDS.ReadXml(File.Open(path,FileMode.Open));
            var NW = new DataTable[15];
            NWDS.Tables.CopyTo(NW,0);
            return NW;

        }
        catch(Exception ex)
        {
            MessageBox.Show("ERROR" + Environment.NewLine + ex.Message);
            return null;
        }
    }

Upvotes: 1

Related Questions