views:

60

answers:

2

I am trying to send a file over a NetworkStream and rebuild it on the client side. I can get the data over correctly (i think) but when I use either a BinaryWriter or a FileStream object to recreate the file, the file is cut off in the beginning at the same point no matter what methodology I use.

  private void ReadandSaveFileFromServer(ref TcpClient clientATF,ref NetworkStream currentStream, string locationToSave)
    {
        int fileSize = 0;
        string fileName = "";

        fileName = ReadStringFromServer(ref clientATF,ref currentStream);
        fileSize = ReadIntFromServer(ref clientATF,ref currentStream);

        byte[] fileSent = new byte[fileSize];

        if (currentStream.CanRead && clientATF.Connected)
        {

            currentStream.Read(fileSent, 0, fileSent.Length);
            WriteToConsole("Log Recieved");

        }
        else
        {
            WriteToConsole("Log Transfer Failed");
        }

        FileStream fileToCreate = new FileStream(locationToSave + "\\" + fileName, FileMode.Create);
        fileToCreate.Seek(0, SeekOrigin.Begin);
        fileToCreate.Write(fileSent, 0, fileSent.Length);
        fileToCreate.Close();

        //binWriter = new BinaryWriter(File.Open(locationToSave + "\\" + fileName, FileMode.Create));
        //binWriter.Write(fileSent);
        //binWriter.Close();

    }

When I step through and check fileName and fileSize, they are correct. The byte[] is also fully populated. Any clue as to what I can do next?

Thanks in advance...

Sean

EDIT!!!:

So I figured out what is happening. When I read a string and then the Int from stream, the byte array is 256 indices long. So my read for string is taking in the int, which then will clobber the other areas. Need to figure this out...

+3  A: 

For one thing, you can use the convenience method File.WriteAllBytes to write the data more simply. But I doubt that that's the problem.

You're assuming you can read all the data in a single call to Read. You're ignoring the return value. Don't do that - instead, read multiple times until either you've read everything you expect to, or you've reached the end of the stream. See this article for more details. If you're using .NET 4, there's a new CopyTo method you may find useful.

(As an aside, your use of ref suggests that you don't understand what it really means. It's well worth making sure you understand how arguments are passed in C#.)

Jon Skeet
Would that explain why the beginning of the file is being cut off?
Sean P
Also isnt passing the networkstream and the connection the proper way to use it since I dont want a "copy" to be made and all actions i take on the object will be reflected globally?
Sean P
@Sean P: They're reference types. It's not going to start copying the data around. Please read the article I linked to, which goes into a lot of detail. But I'd expect the *end* of the file to effectively be cut off, not the start. If the start is being cut off, that suggests there's something wrong in the earlier read operations.
Jon Skeet
+2  A: 

To add to Jon Skeet's answer, your reading code should be:

int bytesRead;
int readPos = 0;
do
{
    bytesRead = currentStream.Read(fileSent, readPos, fileSent.Length);
    readPos += bytesRead;
} while (bytesRead > 0);
Jim Mischel
By `do { ... } until (bytesRead == 0)` Jim means `do { ... } while (bytesRead > 0)`. Unless someone added a do..until statement in C# when I wasn't looking.
Tergiver
@Tergiver: Thanks. You're right. My Pascal is showing (and it's been years since I wrote anything in Pascal) ... I'll fix.
Jim Mischel