﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>Brandon commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>The disposal of the GZipStreams is disposing of the MemoryStream as well even though we want to append to it later. There is no need for all of the inner using statements.</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment15</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment15</guid><pubDate>Wed, 09 Jan 2013 04:48:30 GMT</pubDate></item><item><title>Mikael Syska commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>Waiting... </description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment14</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment14</guid><pubDate>Sun, 06 Jan 2013 01:12:50 GMT</pubDate></item><item><title>wal commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>Hi Ayende, are you hiring and is this the interview question? :)

could you please give us some feedback on the answers and perhaps some more context around this issue. (personally I like PJL's answer)</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment13</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment13</guid><pubDate>Sat, 29 Dec 2012 05:36:31 GMT</pubDate></item><item><title>payam yazdkhasti commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>Sorry, correct code is:
public class GzipStreamDecorator : Stream
    {

        private readonly GZipStream _inputStream;
        private int _count = 0;
        private long _basePosition = 0;
        public GzipStreamDecorator(GZipStream inputStream)
        {
            _inputStream = inputStream;
            _basePosition = _inputStream.BaseStream.Position;
        }
        private Stream BaseStream
        {
            get
            {
                return _inputStream.BaseStream;
            }
        }
        public override bool CanRead
        {
            get { return _inputStream.CanRead; }
        }

        public override bool CanSeek
        {
            get { return _inputStream.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return _inputStream.CanWrite; }
        }

        public override void Flush()
        {
            _inputStream.Flush();
        }

        public override long Length
        {
            get { return _inputStream.Length; }
        }

        public override long Position
        {
            get
            {
                return BaseStream.Position;
            }
            set
            {
                BaseStream.Position = value;
                _basePosition = value;
            }
        }

        private long GetCurrentPosition()
        {
            return _basePosition + ((_count * 8) - 1);
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            var bytesRead = _inputStream.Read(buffer, offset, count);
            _count += bytesRead;
            BaseStream.Position = GetCurrentPosition();
            return bytesRead;
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return _inputStream.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            _inputStream.SetLength(value);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _inputStream.Write(buffer, offset, count);
            _count += count;
        }
    }</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment12</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment12</guid><pubDate>Fri, 28 Dec 2012 11:13:33 GMT</pubDate></item><item><title>Jer commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>Ooh, a puzzle! Intentionally jumping to the bottom to not taint my brain, so apols if this is already answered:

The GZipStream, if I recall correctly, consumes the whole underlying stream in decompress mode...if not that, it definitely won't leave your position where you'd expect it to. A "fix" would be to keep track of where you were after each batch of writes, albeit annoying:

	using(var mem = new MemoryStream())
	{
		using(var gzip = new GZipStream(mem, CompressionMode.Compress, leaveOpen:true))
		{
			gzip.WriteByte(1);
			gzip.WriteByte(2);
			gzip.WriteByte(1);
		}
		var first = mem.Position;
		
		using (var gzip = new GZipStream(mem, CompressionMode.Compress, leaveOpen: true))
		{
			gzip.WriteByte(2);
			gzip.WriteByte(1);
			gzip.WriteByte(2);
		}
		var second = mem.Position;
		
		mem.Position = 0;		
		using (var gzip = new GZipStream(mem, CompressionMode.Decompress, leaveOpen: true))
		{
			Console.WriteLine(gzip.ReadByte());
			Console.WriteLine(gzip.ReadByte());
			Console.WriteLine(gzip.ReadByte());
		}
		mem.Position = first;
	
		using (var gzip = new GZipStream(mem, CompressionMode.Decompress, leaveOpen: true))
		{
			Console.WriteLine(gzip.ReadByte());
			Console.WriteLine(gzip.ReadByte());
			Console.WriteLine(gzip.ReadByte());
		}
	}
</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment11</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment11</guid><pubDate>Fri, 28 Dec 2012 00:38:41 GMT</pubDate></item><item><title>payam yazdkhasti commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>The problem is how GzipStream reads it's base stream.
kerrubin answer is correct but is not good in real application.
I prefer this approch:
first create GzipDecorator like this:
 public class GzipStreamDecorator : Stream
    {

        private readonly GZipStream _inputStream;
        private long _position = 0;
        public GzipStreamDecorator(GZipStream inputStream)
        {
            _inputStream = inputStream;
        }
        private Stream BaseStream
        {
            get
            {
                return _inputStream.BaseStream;
            }
        }
        public override bool CanRead
        {
            get { return _inputStream.CanRead; }
        }

        public override bool CanSeek
        {
            get { return _inputStream.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return _inputStream.CanWrite; }
        }

        public override void Flush()
        {
            _inputStream.Flush();
        }

        public override long Length
        {
            get { return _inputStream.Length; }
        }

        public override long Position
        {
            get
            {
                return _position;
            }
            set
            {
                _position = value;
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            if (_position != BaseStream.Position)
            {
                BaseStream.Position = _position;
            }
            var bytesRead = _inputStream.Read(buffer, offset, count);
            _position += bytesRead;
            return bytesRead;
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return _inputStream.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            _inputStream.SetLength(value);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _inputStream.Write(buffer, offset, count);
        }
    }

then change your code like this:
 using (var mem = new MemoryStream())
            {
                using (var gzip = new GZipStream(mem, CompressionMode.Compress, leaveOpen: true))
                {
                    gzip.WriteByte(1);
                    gzip.WriteByte(2);
                    gzip.WriteByte(1);
                    gzip.Flush();
                }

                using (var gzip = new GZipStream(mem, CompressionMode.Compress, leaveOpen: true))
                {
                    gzip.WriteByte(2);
                    gzip.WriteByte(1);
                    gzip.WriteByte(2);
                    gzip.Flush();
                }


                using (var gzip = new GzipStreamDecorator(new GZipStream(mem, CompressionMode.Decompress, leaveOpen: true)))
                {
                    Console.WriteLine(gzip.ReadByte());
                    Console.WriteLine(gzip.ReadByte());
                    Console.WriteLine(gzip.ReadByte());
                }


                using (var gzip = new GzipStreamDecorator(new GZipStream(mem, CompressionMode.Decompress, leaveOpen: true)))
                {
                    Console.WriteLine(gzip.ReadByte());
                    Console.WriteLine(gzip.ReadByte());
                    Console.WriteLine(gzip.ReadByte());
                }
            }</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment10</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment10</guid><pubDate>Thu, 27 Dec 2012 21:23:32 GMT</pubDate></item><item><title>rvin100 commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>As PJL says, storing the MemoryStream position after each using block seems to be the only solution to make this code works...</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment9</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment9</guid><pubDate>Thu, 27 Dec 2012 11:11:29 GMT</pubDate></item><item><title>kerrubin commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>            using (var mem = new MemoryStream())
            {
                using (var gzip = new GZipStream(mem, CompressionMode.Compress, leaveOpen: true))
                {
                    // mem =&gt; Length: 0, Position: 0, Capacity: 0
                    gzip.WriteByte(1); // mem =&gt; Length: 110, Position: 110, Capacity: 256
                    gzip.WriteByte(2); // mem =&gt; Length: 112, Position: 112, Capacity: 256
                    gzip.WriteByte(1); // mem =&gt; Length: 114, Position: 114, Capacity: 256
                }

                // mem =&gt; Length: 129, Position: 129, Capacity: 256
                using (var gzip = new GZipStream(mem, CompressionMode.Compress, leaveOpen: true))
                {
                    // mem =&gt; Length: 129, Position: 129, Capacity: 256
                    gzip.WriteByte(2); // mem =&gt; Length: 239, Position: 239, Capacity: 256
                    gzip.WriteByte(1); // mem =&gt; Length: 241, Position: 241, Capacity: 256
                    gzip.WriteByte(2); // mem =&gt; Length: 243, Position: 243, Capacity: 256
                }

                // mem =&gt; Length: 258, Position: 258, Capacity: 512
                mem.Position = 0;
                // mem =&gt; Length: 258, Position: 0, Capacity: 512

                using (var gzip = new GZipStream(mem, CompressionMode.Decompress, leaveOpen: true))
                {
                    Console.WriteLine(gzip.ReadByte()); // mem =&gt; Length: 258, Position: 258, Capacity: 512, has read the whole MemoryStream
                    Console.WriteLine(gzip.ReadByte());
                    Console.WriteLine(gzip.ReadByte());
                }

                mem.Position = 129; // size of the MemoryStream after the first compression

                using (var gzip = new GZipStream(mem, CompressionMode.Decompress, leaveOpen: true))
                {
                    Console.WriteLine(gzip.ReadByte());
                    Console.WriteLine(gzip.ReadByte());
                    Console.WriteLine(gzip.ReadByte());
                }
            }</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment8</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment8</guid><pubDate>Thu, 27 Dec 2012 11:00:31 GMT</pubDate></item><item><title>PJL commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>You can make the code work by setting the underlying MemoryStreams Position at position 23 between the two decompression blocks.
Cfr what Erik says it uses internelly a buffer. So you will need to store the memorystream positionsafter every compress block.
 </description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment7</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment7</guid><pubDate>Thu, 27 Dec 2012 10:54:25 GMT</pubDate></item><item><title>Rémi BOURGAREL commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>your Flush are useless http://msdn.microsoft.com/fr-fr/library/system.io.compression.gzipstream.flush.aspx but the dispose should do it. it seems that the first readByte on your GziptStreamm is reading the full memory stream (its position is 250). But I can't figure out where between the Inflater class or the OutputWindow class this is done. Still searching...</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment6</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment6</guid><pubDate>Thu, 27 Dec 2012 10:37:51 GMT</pubDate></item><item><title>Erik commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>The problem is that DeflateStream (which is used by GZipStream) uses a buffer when reading. It tries to read up to 8 kB of the source stream, regardless of the contents, after which the contents of the buffer are parsed. Might be that the easiest solution is to prepend the compressed length of each block, and then feeding only that block to GZipStream.</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment5</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment5</guid><pubDate>Thu, 27 Dec 2012 10:37:40 GMT</pubDate></item><item><title>Ali Kheyrollahi commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>AFAIK, GZipStream on the does its bit:

1) at dispose time for compression
2) at creation for decompression

Considering many compression algorithms do not quite work with writing small buffers (have to work on bigger chunks), this is natural.

Solution is to use stream's CopyTo to copy to another stream and read from that.</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment4</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment4</guid><pubDate>Thu, 27 Dec 2012 10:27:56 GMT</pubDate></item><item><title>rodster commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>Never mind, they are being disposed :-) </description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment3</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment3</guid><pubDate>Thu, 27 Dec 2012 10:25:22 GMT</pubDate></item><item><title>rodster commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>The Flush() does not nothing? You should dispose the stream to flush..</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment2</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment2</guid><pubDate>Thu, 27 Dec 2012 10:22:36 GMT</pubDate></item><item><title>Simon commented on Riddle me this, why won&amp;rsquo;t this code work?</title><description>It's because the memory stream is left at the wrong position after the first GZipStream reads.

Either you can set it to the right position manually by assigning it after the first using block to a variable and re-setting it after the first set of reads, or you can do the writes in one using block  and the reads in one using block, or use separate memory streams for each read/write pair.</description><link>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment1</link><guid>http://ayende.com/160481/riddle-me-this-why-won-t-this-code-work#comment1</guid><pubDate>Thu, 27 Dec 2012 10:16:00 GMT</pubDate></item></channel></rss>