Search code examples
c#protobuf-netsharpziplib

How to writte protobuf serialized content directly to SharpZipLib stream


Is there possible to writte protobuf serialized content directly to SharpZipLib stream? When I try to do this, looks like the provided stream is not filled with the data from protobuf. Later I would need to get back the deserialized entity from provided Zip stream. My code looks like this:

private byte[] ZipContent(T2 content)
    {
        const short COMPRESSION_LEVEL = 4; // 0-9
        const string ENTRY_NAME = "DefaultEntryName";


        byte[] result = null;

        if (content == null)
            return result;

        IStreamSerializerProto<T2> serializer = this.GetSerializer(content.GetType());
        using (MemoryStream outputStream = new MemoryStream())
        {
            using (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream))
            {
                zipOutputStream.SetLevel(COMPRESSION_LEVEL);
                ZipEntry entry = new ZipEntry(ENTRY_NAME);
                entry.DateTime = DateTime.Now;
                zipOutputStream.PutNextEntry(entry);

                serializer.Serialize(zipOutputStream, content);
            }

            result = outputStream.ToArray();
        }

        return result;
    }

private class ProtobufStreamSerializer<T3> : IStreamSerializerProto<T3>
        {
            public ProtobufStreamSerializer()
            {
                ProtoBuf.Serializer.PrepareSerializer<T3>();
            }

    public void Serialize(Stream outputStream, T3 content)
    {
        Serializer.Serialize(outputStream, content);
    }

            public T3 Deserialize(Stream inputStream)
            {
                T3 deserializedObj;
                using (inputStream)
                {
                    deserializedObj = ProtoBuf.Serializer.Deserialize<T3>(inputStream);
                }
                return deserializedObj;
            }
        }

Sample of a class which I'm trying to serialize:

[Serializable]
    [ProtoContract]
    public class Model
    {
        [XmlElement("ModelCode")]
        [ProtoMember(1)]
        public int ModelCode { get; set; }

                ...

    }

Solution

  • This is the problem, I believe (in the original code in the question):

    public void Serialize(Stream outputStream, T3 content)
    {
        using (var stream = new MemoryStream())
        {
            Serializer.Serialize(stream, content);
        }
    }
    

    You're completely ignoring outputStream, instead writing the data just to a new MemoryStream which is then ignored.

    I suspect you just want:

    public void Serialize(Stream outputStream, T3 content)
    {
        Serializer.Serialize(outputStream, content);
    }
    

    I'd also suggest removing the using statement from your Deserialize method: I'd expect the caller to be responsible for disposing of the input stream when they're finished with it. Your method can be simplified to:

    public T3 Deserialize(Stream inputStream)
    {
        return ProtoBuf.Serializer.Deserialize<T3>(inputStream);
    }