Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileStream adding "extra" characters to TXT file

It does not matter if I read a TXT file or a XML file I always see "extra" info added into my file which is saved to disk. We first do the following:

FileStream fs = new FileStream(fileMoverFile.SourcePath, FileMode.Open, FileAccess.Read);

Then we assign fs to a variable of type Stream which we pass to the function below:

private void SaveToDisk(Stream fileStream, string saveToPath)
{
  if (!Directory.Exists(Path.GetDirectoryName(saveToPath)))
  {
    Directory.CreateDirectory(Path.GetDirectoryName(saveToPath));
  }
  FileStream outputStream = new FileInfo(saveToPath).OpenWrite();
  const int bufferSize = 1024;
  byte[] buffer = new byte[bufferSize];
  int bytesRead = fileStream.Read(buffer, 0, bufferSize);
  while (bytesRead > 0)
  {
    outputStream.Write(buffer, 0, bufferSize);
    bytesRead = fileStream.Read(buffer, 0, bufferSize);
  }
  outputStream.Close();
}

When I open the file which was saved to disk, I see extra information which is basically some content of the same file being repeated with some other info which do not belong to the file. Very strange.

What could be causing this?

like image 832
Max Avatar asked Dec 18 '25 03:12

Max


2 Answers

You need to write bytesRead bytes, not bufferSize bytes:

int bytesRead = fileStream.Read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
    outputStream.Write(buffer, 0, bytesRead); // Change this here

Right now, when you reach the end of the input stream, you're potentially writing more data than you read in, which will cause "extra garbage" at the end of the file.

That being said, if your goal is just to copy the stream, you could just use Stream.CopyTo (provided you're in .NET 4+). This avoids the read/write loop entirely, and simplifies your code dramatically:

private void SaveToDisk(Stream fileStream, string saveToPath)
{
  if (!Directory.Exists(Path.GetDirectoryName(saveToPath)))
  {
    Directory.CreateDirectory(Path.GetDirectoryName(saveToPath));
  }
  using(FileStream outputStream = new FileInfo(saveToPath).OpenWrite())
  {
      fileStream.CopyTo(outputStream);
  }
}
like image 130
Reed Copsey Avatar answered Dec 20 '25 19:12

Reed Copsey


You're not using your buffer properly. In the event that the call to fileStream.Read() returns less than bufferSize then your program still continues to read the rest of the buffer that would contain previously-read data.

Here's how you should do it:

using(FileStream output = new FileStream( saveToPath, FileMode.Create, FileAccess.Write )) {

    Byte[] buffer = new Byte[ 32 * 1024 ]; // a 32KB-sized buffer is the most efficient
    Int32 bytesRead;

    while( (bytesRead = fileStream.Read( buffer, 0, buffer.Length ) ) > 0 ) {

        output.Write( buffer, 0, bytesRead );
    }
    output.Flush();
}

Note how I used using and bytesRead to limit the data rewritten to the output.

like image 36
Dai Avatar answered Dec 20 '25 19:12

Dai



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!