0

Possible Duplicate:
Best way to copy between two Stream instances - C#

I know I can use File.Copy but, I'm more interested in doing it a longer way round, just for educational purposes.

Now, the approach I want to discuss is to use a StreamReader and StreamWriter (or FileStreams).

In my mind, I would read the file (as binary) into memory and then write the file to the new location. This strikes me as potential for errors since
1) the entire file is being loaded into memory (and I wouldn't know how big the file is) and
2) it would be time consuming compared to something like copy a byte, paste a byte (which I assume is how streaming works) since we'd have to wait for the entire file to be stored in memory before pasting even begins.

So, a long way to ask, how would I stream a copy and paste job?

Community
  • 1
  • 1
Dave
  • 8,163
  • 11
  • 67
  • 103
  • 2
    It's pretty easy: read a chunk, write a chunk until EOF. But what have you tried? – CodeCaster Oct 10 '12 at 13:42
  • @raman I have tried a few things and ended up getting into a loop - I then start looking on line and every other answer suggests a different route. The issue with the different routes is I don't know if the routes are good or not, hence best to ask on this site where other people can comment on such suggestions – Dave Oct 10 '12 at 13:44
  • @CodeCaster - actually, we have something like that in a project I'm working on but the issue I had again was just not knowing if it was good, mostly because at work I'm stuck on .NET 2.0 - it makes my learning difficult since I am surrounded by old technologies - I didn't want to mention reading/writing chunk by chunk in OP as it 'leads the answer' too much - instead, look at the answers, most agree with you but I also have an async. option and learned lots about File.Copy – Dave Oct 10 '12 at 13:48

3 Answers3

4

So, a long way to ask, how would I stream a copy and paste job?

Instead of reading either each byte separately into memory, or the whole file into memory, you'd go half-way between - create a buffer, e.g. 32K, and ask the input stream to read that much data. Write out however many bytes you've read, and then repeat until there's no more data to read. So something like:

public void Copy(Stream input, Stream output)
{
    byte[] buffer = new byte[32 * 1024];
    int bytesRead;
    while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
    {
        output.Write(buffer, 0, bytesRead);
    }
}

This isn't as efficient as it could potentially be, as you're not reading and writing at the same time. Asynchronous IO would fix that, but make it much more complicated - and it's entirely possible that the OS will be smart enough to keep reading while you're writing anyway...

Note that you would definitely want to use Stream rather than TextReader / TextWriter unless you were actually reading text.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Perfect, exactly the type of answer I was hoping (and your book arrived today from Amazon :) ) – Dave Oct 10 '12 at 13:43
  • _"exactly the type of answer I was hoping"_ - then incorporate your thoughts in your next question. We can't guess what you've alrady thought of. ;-) – CodeCaster Oct 10 '12 at 13:44
  • @DaveRook: See the edit for sample code - which, ironically, is pretty much the same as you'll find in the book somewhere :) – Jon Skeet Oct 10 '12 at 13:44
2

You can read/write the file in blocks of 1 MB (for example). MSDN has an example which shows how to do that.

M4N
  • 94,805
  • 45
  • 217
  • 260
1
  1. Create an empty destination file
  2. Read a buffer from the source file (lets say 1024 bytes)
  3. Write the buffer to the destionation file
  4. Repeat with 2 until everything is done
Eun
  • 4,146
  • 5
  • 30
  • 51