Binary stream '0' does not contain a valid

2019-02-25 02:21发布

I'm working on c# windows service that handles firebird database requests. My problem occurs at random moments (sometimes after 5 minutes, sometimes after just 4 calls to database), when I try to deserialize object on client application. It happens though only at specific position (stops at 18th byte in 54 byte array). Rest of the time the function returns a proper result.


I'm using this function to serialize single object

public byte[] ObjectToByteArray(Object obj)
{
    if (obj == null)
        return null;
    MemoryStream fs = new MemoryStream();
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(fs, obj);
    fs.Seek(0, SeekOrigin.Begin);
    byte[] rval = fs.ToArray();
    fs.Close();
    return rval;
}

I am not serializing any custom classes, only strings and numeric types (firebird api returns them as objects though). I use this to deserialize:

public object ByteArrayToObject(Byte[] Buffer)
{
    BinaryFormatter formatter = new BinaryFormatter();
    MemoryStream stream = new MemoryStream(Buffer);
    stream.Position = 0;
    object rval = formatter.Deserialize(stream); <--- this thing drives me nuts.
    stream.Close();
    return rval;
}

and main fnct in client aplication. Sorry for ugly code,

    public List<object[]> ByteToList(byte[] data, int[] pomocnicza)
    {
        //pomocnicza table contains size of (original) particular column of list in bytes
        int size_row = 0;
        foreach (int i in pomocnicza)
        { size_row += i; }
        List<object[]> result = new List<object[]>();
        int iterator = 0;
        for (int i = 0; i < data.Length / size_row ; i++)
        {
            object[] zxc = new object[3];
            int l = pomocnicza.Length/4;
            for (int j = 0; j < l; j++)
            {
                byte[] tmp = new byte[pomocnicza[j*4]];
                System.Array.Copy(data, iterator, tmp, 0, pomocnicza[j*4]);
                object ffs = ByteArrayToObject(tmp);
                zxc[j] = ffs;
                iterator += pomocnicza[j*4];
            }
            result.Add(zxc);
        }
        return result;
    }

What is baffling me is that it works in most cases, but inevitably causes to throw an error. Thing that it happens on random makes pinpointing it harder. Please help.


@EDIT This is how I read the input:

    public List<object[]> RetrieveSelectData(FbConnection dbConn, string SQLCommand)
    {
        using (var command = dbConn.CreateCommand())
        {
            command.CommandText = SQLCommand;
            using (var reader = command.ExecuteReader())
            {
                var rows = new List<object[]>();
                while (reader.Read())
                {
                    var columns = new object[reader.FieldCount];
                    reader.GetValues(columns);
                    rows.Add(columns);
                }
                return rows;
            }
        }
    }

and then serialize with this function

    public byte[] ListToByte(List<object[]> lista, out int[] rozmiary)
    {
        int size= 0;
        rozmiary = new int[lista[0].Length];
        for (int i = 0; i < lista[0].Length; i++)
        {
            byte[] test = this.ObjectToByteArray(lista[0][i]);
            size+= test.Length;
            rozmiary[i] = test.Length;
        }
        size*= lista.Count;
        byte[] result = new byte[size];
        int index = 0;
        for (int i = 0; i < lista.Count; i++)
        {
            for (int j = 0; j < lista[i].Length; j++)
            {
                byte[] tmp = this.ObjectToByteArray(lista[i][j]);                  
                tmp.CopyTo(result, index);
                index += tmp.Length;
            }
        }
        return result;
    }

标签: c# tcp firebird
2条回答
劳资没心,怎么记你
2楼-- · 2019-02-25 03:05

I have found the bug. The code above works fine, but care for encoding in some cases(!), so feel free to use it. The problem laying in another part of a program, where I mistyped and send 4 bytes BUT the client app was told to receive 8, so in most cases it filled it in with zeros, but sometimes it got it from next pack of data.

It was @Marc Gravell and his blog that made me look over and over again to eventually find the source.

查看更多
干净又极端
3楼-- · 2019-02-25 03:26

If you are using above deserializing methods & also call them while getting stream from clientstream OR other streams.... skip it. try to use directly those streams with formatter. Like Below :

NetworkStream clientStream = client.GetStream();
Object src = (Object)formatter.Deserialize(clientStream);
查看更多
登录 后发表回答