4

According to the MSDN documentation for FileStream.SafeFileHandle:

The SafeFileHandle property automatically flushes the stream and sets the current stream position to 0. This allows the file to be moved or the stream position to be reset by another stream using the SafeFileHandle returned by this property.

However, my tests seem to indicate that the stream position is not changed.

Consider the following code:

using System;
using System.IO;

namespace Demo
{
    internal static class Program
    {
        public static void Main()
        {
            Directory.CreateDirectory("C:\\TEST");
            var buffer = new byte[1024];

            using (var file = new FileStream("C:\\TEST\\TEST.BIN", FileMode.Create))
            {
                file.Write(buffer, 0, buffer.Length);
                Console.WriteLine(file.Position);  // Prints 1024
                var dummy = file.SafeFileHandle;
                // dummy.Dispose();                // Uncommenting this line will make the next line throw.
                Console.WriteLine(file.Position);  // Still prints 1024!
            }
        }
    }
}

If accessing SafeFileHandle really did reset the current stream position to 0, I'd have expected the second WriteLine() to print 0.

I have other tests where I actually use SafeFileHandle with the Windows API ReadFile() and WriteFile() methods, and even then it doesn't appear to change the file pointer.

I have some code that uses SafeFileHandle, so it's pretty important to me whether the stream position will be changed or not!

Have I misunderstood the documentation, or is it incorrect? Or does it change the stream position sometimes? (That would be a nightmare!)

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Doesn't the documentation mean that the file is flushed and stream position is reset when the handle is closed or disposed? – adrianm Apr 30 '13 at 09:36
  • @adrianm Well if you close the SafeHandle via `SafeHandle.Close()` you can no longer access the file via the `FileStream` so that doesn't really make much sense... I've updated my question with this info. – Matthew Watson Apr 30 '13 at 09:39
  • This is the commented [source code](http://www.dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/whidbey/REDBITS/ndp/clr/src/BCL/System/IO/FileStream@cs/2/FileStream@cs) for FileStream class. There are different positions in it (_pos, _readPos, _writePos). Hope it will help you. – Vladimir Apr 30 '13 at 09:45
  • It doesn't alter what you are seeing, but note that you create a directory `C:\TEST`, but write your file into the current directory (you probably wanted to say `new FileStream("C:\\TEST\\TEST.BIN")`). – Christian.K Apr 30 '13 at 09:56

1 Answers1

5

I think the documentation is actually talking about the input and output buffers used by FileStream ("FileStream buffers input and output for better performance.").

If you use the .NET library reference source, you can see that the SafeFileHandle property actually flushes all buffers (i.e. caches) and resets their positions back to zero. It doesn't touch the variable that holds the information about how far the file has really been read (or written). The Position property in turn, always uses that variable (plus the buffer /cache offsets) to return it's value.

The important part seems to be this:

This allows the file to be moved or the stream position to be reset by another stream using the SafeFileHandle returned by this property.

Basically, SafeFileHandle guarantees you, that you can use the return value (e.g. with SetFilePointer) to access the file and have no issues with the (eventual) caching of the FileStream instance.

Christian.K
  • 47,778
  • 10
  • 99
  • 143
  • 1
    I was about to write the same thing, +1. I think it's a bug in the documentation actually, because it is (at least) not well explained. The position remains unchanged. – ken2k Apr 30 '13 at 09:52
  • Well that sounds plausible. It's a bit odd that the documentation explicitly says "current stream position", especially when the documentation for `FileStream.Position` says `Gets or sets the current position of this stream`. So the documentation thinks that "current stream position" is NOT the same as "current position of this stream"! You can understand my confusion! – Matthew Watson Apr 30 '13 at 09:54
  • 1
    @ken2k If it was up to me ;-) I would also say that the documentation is buggy / imprecise here (given that my analysis is correct in the first place). – Christian.K Apr 30 '13 at 09:58
  • @Christian.K I definitely understand the confusion, this part of the documentation should be removed IMO. The only thing that matters as Christian K well explained, is that there won't be issue with the internal cache system of `FileStream` when using the safe file handle with P/Invoke. – ken2k Apr 30 '13 at 10:06