Click here to Skip to main content
16,014,392 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am using the following code for compression of data at the server:

The job of this method is to execute the specified method passed as a string and return the object as a compressed stream (serializing the object and compressing the serialized stream) to the client application. When value is returned to the client, the decompression takes place there and the decompressed stream is deserialized to obtain the actual object

The method below takes parameters as name of method to be executed including the methodarguments and argumenttypes to distinguish the different overloaded methods and identify the exact method and avoid ambiguity. ExecObject is the object with which the specified method will be invoked.



//SERVER SIDE METHOD
public Stream CompressedMethodCall(string MethodName, object[] MethodArguments, Type[] ArgumentTypes, object ExecObject)
        {
           
            object Result;//the object which will be returned by the specified methodname
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Serializer; //to serialize the object
            System.IO.Compression.GZipStream Compressor;//to compress the serialized object
            Stream SerializedStream;//contains the stream which is serialized
            Stream CompressedStream;//contains the compressed serailized stream
            byte[] Buffer;
            try
            {
                MethodInfo mi = ExecObject.GetType().GetMethod(MethodName, ArgumentTypes);
                Result = mi.Invoke(ExecObject, MethodArguments);//now result has the object which should be serialized and compressed
                if (Result != null)
                {
                    Serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();//binaryformatter is used for compact serialization
                    SerializedStream = new MemoryStream();
                    Serializer.Serialize(SerializedStream, Result);//now SeralizedStream has the serialized object
                    SerializedStream.Position = 0;
                    Result = null;
                    CompressedStream = new MemoryStream();
                    Compressor = new System.IO.Compression.GZipStream(CompressedStream, System.IO.Compression.CompressionMode.Compresstrue);
                    while (SerializedStream.Position != SerializedStream.Length)
                    {
                        long BytesRemaining = SerializedStream.Length - SerializedStream.Position + 1;
                        if (BytesRemaining < BufferLength)
                            Buffer = new byte[BytesRemaining];
                        else
                            Buffer = new byte[BufferLength];
                        SerializedStream.Read(Buffer, 0, Buffer.Length);
                        Compressor.Write(Buffer, 0, Buffer.Length);
                    }
                    SerializedStream.Close();
                    CompressedStream.Position = 0;
                    return CompressedStream;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
            return null;
        }



Now the returned value(compressed stream) is used to obtain the actual object. I am doing it this way

//CLIENT SIDE STATIC METHOD

public class DeCompressor
   {
       const int BufferLength = 4096;
       public static object GetObject(Stream CompressedStream)
       {
           object Result;
           BinaryFormatter DeSerializer = new BinaryFormatter();
           Stream SerializedStream = new MemoryStream();
           CompressedStream.Position = 0;
           GZipStream DeCompressor = new GZipStream(CompressedStream, CompressionMode.Decompress,true);
           byte[] Buffer;
           int Read = 1;
           try
           {
               while (Read > 0)
               {
                   Buffer = new byte[BufferLength];
                   Read = DeCompressor.Read(Buffer, 0, BufferLength);
                   if (Read == 0) Read = DeCompressor.Read(Buffer, 0, BufferLength);//sometimes it decompressing 0 bytes eventhough there is data to be decmopressed. If I again call Read() it will decompress. To avoid this, I am using it twice
                   SerializedStream.Write(Buffer, 0, Read);
               }
               CompressedStream.Close();
               SerializedStream.Position = 0;
               Result = DeSerializer.Deserialize(SerializedStream);
               SerializedStream.Close();
               return Result;
           }
           catch (Exception ex)
           {
               Castor.CastorMessageBox.Show(ex.Message);
               return null;
           }
       }



This method is working fine. But sometimes decompression is not producing the exact stream which was produced at server. Due to this, deserialization process is not successful and I am unable to retreive the actual object.


I am using VS2008. Any help would be appreciated
Posted
Updated 8-Jul-10 23:05pm
v2
Comments
Christian Graus 9-Jul-10 5:02am    
How does it differ ? Are you sure the compression worked fine ?
OriginalGriff 9-Jul-10 5:30am    
Stage one: Check both methods on the same PC. Extract your methods to a test project. Compress a suitable buffer, feed it's output to the decompresser, and manually check byte-by-byte they are the same. Repeat for several sample datasets. If they are the same proceed to stage two.

Stage two. Check the data transfer. Using a similar set up to stage one, compress your data, send it to your server, which turns it round and sends it back. The original pc then checks the returned data is the same as the sent data. Repeat. If it is the same proceed to stage three.

Stage three. As stage two, but the data is decompressed at the server, and sent back uncompressed to the original PC for comparison.

At which stage it fails tells you where to concentrate.
ameem85 9-Jul-10 5:52am    
Yes, Compression worked fine. But decompression is not always working. Not working in the sense, it is not producing the actual data which was compressed. For example the actual data is of 10485760 bytes, and after compression say if the size is 1048576 bytes. Then the decompression should give me 10485760 bytes again, which is the actual data. But sometimes (not always) the data in bytes I get after decompression is less than the actual data which was originally compressed. Due to this deserialization process fails with exception "End of Stream Encountered before parsing was done". Sometimes, desarialization works even if the decompressed data is not exactly the actual data. This issue is very annoying to the client users, when the user requests any large object and he encounters this error. I tried debugging it, but I am unable to find where I am going wrong.
OriginalGriff 9-Jul-10 7:28am    
Which stage did it fail at?
ameem85 10-Jul-10 3:54am    
I already tested the way you said. Both client and server code was run at the same machine. It is failing while decompressing the data. I checked the decompressed data byte-by-byte with the original data. It is same but for some datasets the data is lesser than the actual data in some hundreds of bytes. This behavior is varying for different datasets. Most of the times it is working correctly for some datasets only the problem is intruding

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900