5

I'm writing code that deals with a file that uses hashes. I need to read a chunk, then hash it, then write it, then read another chunk, etc.

In other words, I need to do a lot of reading and writing. I'm sure this is really simple, but I just wanted to run it by the pros...

Is it possible, and acceptable to do something like:

BinaryReader br = new BinaryReader (File.OpenRead(path));
BinaryWriter bw = new BinaryWriter (File.OpenWrite(path));
br.dostuff();
bw.dostuff();

I remember running into some sort of conflicting file streams error when experimenting with opening and writing to files, and I'm not sure what I had done to get it. Is it two file streams that's the issue? Can I have one stream to read from and write to?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
mowwwalker
  • 16,634
  • 25
  • 104
  • 157

1 Answers1

3

This is perfecty possible and desired, A technicality, if your write method doesn't change the length of the file and is always behind the reader, this should not give any problems. In fact, from an API point of view, this is desirable since this allows the user to control where to read from and where to write to. (It's a recommended specification to write to a different file, in case any bad things happen during the encryption process, your input file wont be messed up).

Something like:

protected void Encrypt(Stream input, Stream output)
{
    byte[] buffer = new byte[2048];

    while (true)
    {
        // read 
        int current = input.Read(buffer, 0, buffer.Length);
    if (current == 0)
                     break;

        // encrypt
        PerformActualEncryption(buffer, 0, current);

        // write
        output.Write(buffer, 0, current);
    }   
}

public void Main()
{
    using (Stream inputStream  = File.Open("file.dat", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (Stream outputStream = File.Open("file.dat", FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
    {
        Encrypt(inputStream, outputStream);
    }
}

Now since you're using an encryption, i would even recommend to perform the actual encryption in another specialized stream. This cleans the code up nicely.

class MySpecialHashingStream : Stream
{
...
}

protected void Encrypt(Stream input, Stream output)
{
    Stream encryptedOutput = new MySpecialHashingStream(output);
    input.CopyTo(encryptedOutput);
}
Polity
  • 14,734
  • 2
  • 40
  • 40
  • 2
    @Walkerneo - You can but i wouldnt recommend it. File handeles are optimized with caching, Seeking is less optimized (do a test and you will see). Besides that, my point was to allow for API flexibility and safety which you will loose when working with only 1 filehandle for both reading and writing – Polity Dec 28 '11 at 10:32
  • With a small modification: opening the file twice doesn't seem to work as described here. But if the stream is common, it already works fine: `using (var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) using (var reader = new BinaryReader(stream)) using (var writer = new BinaryWriter(stream)) { ... } ` – Gábor Jan 10 '19 at 22:49