Search code examples
c#file-iostreamreader

c# - StreamReader and seeking


Can you use StreamReader to read a normal textfile and then in the middle of reading close the StreamReader after saving the current position and then open StreamReader again and start reading from that poistion ?

If not what else can I use to accomplish the same case without locking the file ?

I tried this but it doesn't work:

var fs = File.Open(@ "C:\testfile.txt", FileMode.Open, FileAccess.Read);
var sr = new StreamReader(fs);

Debug.WriteLine(sr.ReadLine()); //Prints:firstline

var pos = fs.Position;

while (!sr.EndOfStream) 
{
    Debug.WriteLine(sr.ReadLine());
}

fs.Seek(pos, SeekOrigin.Begin);

Debug.WriteLine(sr.ReadLine());
//Prints Nothing, i expect it to print SecondLine.

Here is the other code I also tried :

var position = -1;
StreamReaderSE sr = new StreamReaderSE(@ "c:\testfile.txt");

Debug.WriteLine(sr.ReadLine());
position = sr.BytesRead;

Debug.WriteLine(sr.ReadLine());
Debug.WriteLine(sr.ReadLine());
Debug.WriteLine(sr.ReadLine());
Debug.WriteLine(sr.ReadLine());

Debug.WriteLine("Wait");

sr.BaseStream.Seek(position, SeekOrigin.Begin);
Debug.WriteLine(sr.ReadLine());

Solution

  • Yes you can, see this:

    var sr = new StreamReader("test.txt");
    sr.BaseStream.Seek(2, SeekOrigin.Begin); // Check sr.BaseStream.CanSeek first
    

    Update: Be aware that you can't necessarily use sr.BaseStream.Position to anything useful because StreamReader uses buffers so it will not reflect what you actually have read. I guess you gonna have problems finding the true position. Because you can't just count characters (different encodings and therefore character lengths). I think the best way is to work with FileStream´s themselves.

    Update: Use the TGREER.myStreamReader from here: http://www.daniweb.com/software-development/csharp/threads/35078 this class adds BytesRead etc. (works with ReadLine() but apparently not with other reads methods) and then you can do like this:

    File.WriteAllText("test.txt", "1234\n56789");
    
    long position = -1;
    
    using (var sr = new myStreamReader("test.txt"))
    {
        Console.WriteLine(sr.ReadLine());
    
        position = sr.BytesRead;
    }
    
    Console.WriteLine("Wait");
    
    using (var sr = new myStreamReader("test.txt"))
    {
        sr.BaseStream.Seek(position, SeekOrigin.Begin);
        Console.WriteLine(sr.ReadToEnd());
    }