<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Miguel de Icaza's blog - Latest Comments in Stream.CopyStream - Miguel de Icaza</title><link>http://migueldeicaza.disqus.com/</link><description></description><atom:link href="https://migueldeicaza.disqus.com/streamcopystream_miguel_de_icaza/latest.rss" rel="self"></atom:link><language>en</language><lastBuildDate>Thu, 11 Dec 2008 15:51:18 -0000</lastBuildDate><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-4333709</link><description>&lt;p&gt;Actually, it worked out rather well for a serial port interface I was using a couple years ago.&lt;/p&gt;&lt;p&gt;I'll agree that quite a few methods are predicated on re-enumerability, but I don't think that breaks things, if you're of the mind that IDisposable isn't abused when you use it for scoping Transactions (for example).&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Keith J. Farmer</dc:creator><pubDate>Thu, 11 Dec 2008 15:51:18 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2779855</link><description>&lt;p&gt;Java's streams are also byte-oriented and raw.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Martin</dc:creator><pubDate>Wed, 01 Oct 2008 11:51:16 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2655750</link><description>&lt;p&gt;Hah. With all these wheels being re-invented everywhere, Mono.Rocks is definitely a good idea.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">commenter</dc:creator><pubDate>Sat, 27 Sep 2008 05:41:56 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2655746</link><description>&lt;p&gt;I called mine Decant, as in 'decant the data from one stream into another'.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">commenter</dc:creator><pubDate>Sat, 27 Sep 2008 05:41:17 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2640662</link><description>&lt;p&gt;&amp;gt; PS: TextReader should implement a 'Lines' enumerator.&lt;/p&gt;&lt;p&gt;Indeed it should, which is why Mono.Rocks has a TextReader.Lines() extension method in rocks-playground. :-)&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Pryor</dc:creator><pubDate>Fri, 26 Sep 2008 10:07:52 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2639095</link><description>&lt;p&gt;Implementing such a method might lead to some confusion. On the other hand lots of people need it, so having it would be nice.&lt;br&gt;But please name it appropriately: I think you want a "CopyData" Method (you want to copy the data that is transported by the stream not the stream itself if I understand correctly)&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Foxfire</dc:creator><pubDate>Fri, 26 Sep 2008 07:30:26 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2633063</link><description>&lt;p&gt;Ah, see that's where i think where we differ. That's just a simple myStream.Write (otherStream). It's completely different to a TeeStream or SplitStream as i described earlier ;) I did say that a writing the contents of one stream to another was easy, but i didn't think that's what was being asked in the original question. Maybe i'm wrong there.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Alan</dc:creator><pubDate>Thu, 25 Sep 2008 18:47:28 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2632598</link><description>&lt;p&gt;Alan, I don't see why it would this would be difficult to implement CopyStream having Stream as a source and target. Here's my implementation that I use in projects:&lt;br&gt;&lt;a href="http://gist.github.com/12956" rel="nofollow noopener" target="_blank" title="http://gist.github.com/12956"&gt;http://gist.github.com/12956&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In general, though, this only useful for low latency and small streams. In environments where scalability is key, copying may be best performed using async I/O (BeginRead-BeginWrite).&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Atif Aziz</dc:creator><pubDate>Thu, 25 Sep 2008 18:08:17 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2625048</link><description>&lt;p&gt;Nope, I hadn't heard of that.&lt;br&gt;I checked the website and found that they've somehow managed to hack into my computer and steal my Int32.Times extension method, so I'll be contacting my lawyers forthwith.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">commenter</dc:creator><pubDate>Thu, 25 Sep 2008 10:01:29 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2624055</link><description>&lt;p&gt;That is a really good idea.&lt;/p&gt;&lt;p&gt;Are you aware of "Mono.Rocks"?    It is a library of extension methods that some developers have been prototyping to add useful extension methods.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">migueldeicaza</dc:creator><pubDate>Thu, 25 Sep 2008 08:36:14 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2623851</link><description>&lt;p&gt;Well, if all you're looking for is:&lt;/p&gt;&lt;p&gt;stream2.Write(stream1), then that's trivial enough to implement. However if you want something more along the lines of giving you three identical copies of the same stream so you can independently read from the copies and progress the initial stream, then it's a lot harder.&lt;/p&gt;&lt;p&gt;byte[] bytes = GetData();&lt;br&gt;MemoryStream a = new MemoryStream(bytes);&lt;br&gt;MemoryStream b = new MemoryStream(bytes);&lt;br&gt;MemoryStream c = new MemoryStream(bytes);&lt;/p&gt;&lt;p&gt;If you want a CopyStream that essentially does the above except using a Stream as the base rather than a byte[] as the base, the task is very difficult.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Alan</dc:creator><pubDate>Thu, 25 Sep 2008 08:14:10 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2623510</link><description>&lt;p&gt;This was a good question.&lt;br&gt;It just goes to show that if you ask a question like this you will get lots of people trying to look clever by thinking up reasons why it can't be done.&lt;br&gt;I've implemented this function multiple times. If the framework can have File.WriteAllLines then it sure as hell should have a CopyStream method. If people have esoteric situations where a simple implementation wouldn't work.... well then, don't use the simple implementation!&lt;/p&gt;&lt;p&gt;PS: TextReader should implement a  'Lines' enumerator.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">commenter</dc:creator><pubDate>Thu, 25 Sep 2008 07:25:52 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2623092</link><description>&lt;p&gt;I guess the problem is that such implementation ( or even definition as an abstract method ) requeres a lot of understanding about the diferences between two streams. Such a copy would need to be "secured" by some contract that regulates what a CopyStream should mean, and right now I belive that there ara as many CopyStreams as streams types ( buffered , unbuffered , etc. ). The extension methods are probably the best solution.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Angel Ochoa</dc:creator><pubDate>Thu, 25 Sep 2008 06:10:03 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2622812</link><description>&lt;p&gt;Well, a TeeStream class wouldn't be that complex. A lot of the complexity that i saw in a class which allowed copying a stream an arbitrary number of times, with each copy having the ability to progress the initial stream would be gone. The implementation would be just read-once, write many. No threadin concerns there.&lt;/p&gt;&lt;p&gt;Something like:&lt;/p&gt;&lt;p&gt;public class TeeStream : Stream&lt;br&gt;{&lt;br&gt;    public TeeStream (IEnumerable&amp;lt;stream&amp;gt; destinationStreams)&lt;br&gt;    {&lt;/p&gt;&lt;p&gt;    }&lt;br&gt;}&lt;/p&gt;&lt;p&gt;would be fairly easy to implement. Something like that should already be in the BCL I suppose. There's no real reason why not.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Alan</dc:creator><pubDate>Thu, 25 Sep 2008 05:05:07 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2622692</link><description>&lt;p&gt;Such an addition would be _wonderful_!  Especially if it supported asynchronous copying/splitting.  For instance, moving gigs of data from a network stream to another network stream (proxying) and a file stream (caching) simultaneously without blocking threads is a pretty complex operation.  I would love to see a community vetted implementation of it.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Steve Bjorg</dc:creator><pubDate>Thu, 25 Sep 2008 04:33:39 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2620424</link><description>&lt;p&gt;I don't think it's quite that bad, as sane defaults exist for your concerns.&lt;/p&gt;&lt;p&gt;Buffer size?  A reasonable number, e.g. 4096 or 8192 bytes -- something close to filesystem block size without causing too much trouble for the GC.&lt;/p&gt;&lt;p&gt;Time outs?  Ignore them.  If timeouts are needed, then the calling code can set Stream.ReadTimeout and Stream.WriteTimeout appropriately; I don't see why a helper method should care.&lt;/p&gt;&lt;p&gt;Retries?  Retries are evil: &lt;a href="http://blogs.msdn.com/oldnewthing/archive/2005/11/07/489807.aspx" rel="nofollow noopener" target="_blank" title="http://blogs.msdn.com/oldnewthing/archive/2005/11/07/489807.aspx"&gt;http://blogs.msdn.com/oldne...&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A utility method doesn't need to be the be-all, end-all method to be useful.  It just needs to provide a sane solution to a problem that would otherwise be hand-written every time.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Pryor</dc:creator><pubDate>Thu, 25 Sep 2008 00:32:11 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2620340</link><description>&lt;p&gt;Alan,&lt;/p&gt;&lt;p&gt;In that case, you would not use CopyStream, it is a perfectly fine restriction to say that the stream is consumed after CopyStream is finished.&lt;/p&gt;&lt;p&gt;There is nothing preventing a "TeeStream" (like the Unix Tee command) to duplicate the contents as it goes and composing the above described operation using this.&lt;/p&gt;&lt;p&gt;But many times I do not care about keeping a copy, and I do not care about chunked output, or if its network or not, I just want to move the bytes from the source to the destination.   And I have seen various broken versions of this loop, or versions that are too optimistic and have never been properly tested.&lt;br&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">migueldeicaza</dc:creator><pubDate>Thu, 25 Sep 2008 00:22:52 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2597192</link><description>&lt;p&gt;I actually experimented with this in rocks-playground, providing a `IEnumerable&amp;lt;byte&amp;gt; ToEnumerable(this Stream)` method.  It was cute.&lt;/p&gt;&lt;p&gt;I removed it.&lt;/p&gt;&lt;p&gt;The problem is that a Stream-backed IEnumerable&amp;lt;t&amp;gt; IS NOT an IEnumerable&amp;lt;t&amp;gt;, as it tends to break things rather badly.  For example, many LINQ methods (and rocks-playgound IEnumerable&amp;lt;t&amp;gt; extension methods) assume that the sequence can be consumed repeatedly.&lt;/p&gt;&lt;p&gt;A stream-backed IEnumerable&amp;lt;byte&amp;gt; can only be iterated over *once*, reliably.  Beyond that, and you start getting into seeking issues, which _really_ start killing the thought (NetworkStreams don't seek), etc.&lt;/p&gt;&lt;p&gt;It's cute, but likely unworkable in practice (at least in my experience).&lt;/p&gt;&lt;p&gt;In spite of this, I'm still keeping some "once-only" iterator types (TextReaderRocks.Lines() and TextReaderRocks.Words()), as I think they're useful even if they can only be used once, but it's something you need to be careful about.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Pryor</dc:creator><pubDate>Thu, 25 Sep 2008 00:05:32 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2589080</link><description>&lt;p&gt;I think you don't fully understand .NET's Stream concept, as it's closer to C++ than Java.&lt;/p&gt;&lt;p&gt;Stream is _only_ byte oriented.  No encodings, no endianness, no line endings, just raw data.  It is thus analogous to the C++ std::streambuf type, if even more primitive (there is no wstreambuf equivalent).&lt;/p&gt;&lt;p&gt;StreamReader and StreamWriter are responsible for text-oriented manipulation, such as encoding issues, end of line encodings, etc., which is what std::istream and std::ostream deal with in C++ (and more).&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Pryor</dc:creator><pubDate>Wed, 24 Sep 2008 22:48:56 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2588393</link><description>&lt;p&gt;How could System.IO.Stream ever implement CopyStream? It'd be a nightmare to implement!&lt;/p&gt;&lt;p&gt;The problem is that the Stream in question could be *anything*, i.e. a NetworkStream. By reading data from this stream (in order to make a copy) you will render the initial stream unusable because you've already read the data out, and you cannot rewind it. What you end up with is a single usable version of the stream instead of two.&lt;/p&gt;&lt;p&gt;If you want to be able to 'Copy' a stream, you have to do it manually. You need to read all the data from the initial stream as a byte[], then instantiate all the MemoryStreams you want from this byte[].&lt;/p&gt;&lt;p&gt;Suppose you wanted to implement Stream.CopyStream, you could create a class like&lt;/p&gt;&lt;p&gt;public class StreamSplitter : Stream&lt;br&gt;{&lt;br&gt;    public StreamSplitter (Stream initialStream)&lt;br&gt;    {&lt;br&gt;        // Do stuff&lt;br&gt;    }&lt;/p&gt;&lt;p&gt;    public Stream GetCopy()&lt;br&gt;    {&lt;br&gt;        // Do stuff&lt;br&gt;    }&lt;br&gt;}&lt;/p&gt;&lt;p&gt;Internally the StreamSplitter will read from the initial stream and store the data in a byte[]. GetCopy will then return a MemoryStream type class based on this byte[]. This class would have the ability to tell the StreamSplitter to get more data from the initial stream and make it available to all the copies which have been created.&lt;/p&gt;&lt;p&gt;The problem is that any copy can initiate this request for more data at any time. This is a pain in the ass for thread synchronisation with regards to the initial stream. Then you have more threading problems when you try making this new data available to the existing copies. All i can say is that there's no way i'd ever implement something like that ;)&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Alan</dc:creator><pubDate>Wed, 24 Sep 2008 21:51:02 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2580601</link><description>&lt;p&gt;The comments about extension methods are completely on the mark:  seperate common operations from the object, when those operations don't have any direct bearing on the state.  Creating a chain of adapters (buffer, splitter, copier, etc) would be more useful, but only if they didn't belong directly to stream.  In fact, I would be very tempted to put them as extensions to IEnumerable&amp;lt;t&amp;gt;, and have an adapter to transform Stream into IE&amp;lt;t&amp;gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Keith J. Farmer</dc:creator><pubDate>Wed, 24 Sep 2008 18:55:05 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2575167</link><description>&lt;p&gt;I have also implemented that quite a few times and been annoyed by the need to do so.&lt;/p&gt;&lt;p&gt;But I think I know why it is not part of Stream: There are simply too many decisions to make if such a method must robustly handle all kinds of streams:What buffer size to use; what is a suitable time-out, particularly for network streams; should failed operations be retried, and how many times etc..&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Rasmus</dc:creator><pubDate>Wed, 24 Sep 2008 15:41:17 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2575144</link><description>&lt;p&gt;Sounds like another addition for rocks-playground!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Pryor</dc:creator><pubDate>Wed, 24 Sep 2008 15:40:13 -0000</pubDate></item><item><title>Re: Stream.CopyStream - Miguel de Icaza</title><link>http://tirania.org/blog/archive/2008/Sep-24.html#comment-2574204</link><description>&lt;p&gt;With extension methods, it's a bit cleaner than it used to be (I call mine CopyTo), but yes I have implemented a variation of this many, many times.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Derek</dc:creator><pubDate>Wed, 24 Sep 2008 15:28:39 -0000</pubDate></item></channel></rss>