how to use seek() in StreamReader class?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

We can use seek() in the FileStream class,as we know.
But I found that seek() is not work correctly in StreamReader.
Who can tell me how to use seek() correctly in StreamReader?
thanks a lot!
I use the seek() like this:
StreamReader r;
.......
r.BaseStream.seek(.....);
 
Tiger,

Try calling r.DiscardBufferedData() to clear the stream's buffer of data.
If you continue to have problems please post your code and exactly what you
want to accomplish.

Hope this helps.
 
Brian Brown,
My code is like this:
FileStream fs;
fs=new FileStream("cc.txt",FileMode.Open,FileAccess.Read);
StreamReader r=new StreamReader(fs);
Console.WriteLine((char)r.Peek());
//r.DiscardBufferedData();
r.BaseStream.Seek(5,SeekOrigin.Current);
//r.DiscardBufferedData();
Console.WriteLine((char)r.Peek());
The content of cc.txt is :abcdefghijklmnop
I thought the result which is printed on sreen is:
a
f
But in fact is
a
a
why?
I have tried r.DiscardBufferedData(),which is remarked in my code,but the
result is
a
?
I hope your reply,thanks a lot!
 
Tiger,

I am glad that you posted your code. From the earlier posting I was
thinking that you had data left over in the buffer. Now I think that I see
what you are trying to accomplish. I will attempt to explain…

Seek is a method of the BaseStream (i.e. FileStream). If you call Seek(5,
SeekOrigin.Current) on the BaseStream (remember this is the FileStream not
the StreamReader…) you have moved the file pointer forward 5 places. If you
call the BaseStream.Read method you will see that the returned value is
offset 5 places from where the pointer used to be pointing.

The StreamReader has no such method as Seek. Since this is the case you will
not get the results you expect when you call StreamReader.Peek(). The Peek()
method uses a different pointer to the data. It will see the next character
in the stream according to where the StreamReader is pointing not where the
BaseStream pointer is located. I have posted some sample code below to
demonstrate my point.

I hope this helps

---------------
using System;
using System.IO;
using System.Text;

..
..
..
const String FILENAME = @"D:\cc.txt";

FileStream fs;
fs=new FileStream(FILENAME,FileMode.Open,FileAccess.Read);
StreamReader r=new StreamReader(fs);
Byte[] myByteArray = new Byte[1];
ASCIIEncoding myEncoding = new ASCIIEncoding();

//call seek on the base stream (i.e. the filestream)
r.BaseStream.Seek(0,SeekOrigin.Begin);
//read the first character from the file stream
r.BaseStream.Read(myByteArray,0,1);
//output to the console
Console.WriteLine(myEncoding.GetString(myByteArray));

//call seek on the base stream and move it up 5 places
r.BaseStream.Seek(5,SeekOrigin.Current);
//read the first character from the file stream
r.BaseStream.Read(myByteArray,0,1);
//output to the console
Console.WriteLine(myEncoding.GetString(myByteArray));

//close the streams
r.Close();
fs.Close();
 
Tiger said:
Brian Brown,
My code is like this:
FileStream fs;
fs=new FileStream("cc.txt",FileMode.Open,FileAccess.Read);
StreamReader r=new StreamReader(fs);
Console.WriteLine((char)r.Peek());
//r.DiscardBufferedData();
r.BaseStream.Seek(5,SeekOrigin.Current);
//r.DiscardBufferedData();
Console.WriteLine((char)r.Peek());

<snip>

Just to explain in a slightly different way to Brian (maybe).

When you first call r.Peek(), the StreamReader is reading a chunk of
data from the stream. That leaves the stream positioned later in the
data than you'd expect - at the end of the file, in your particular
case. You're then telling the stream to reposition itself 5 bytes later
- i.e. still at the end of the file. You're then telling the
StreamReader to discard the buffered data (assuming you've removed the
comment), and it then tries to read from the stream, and finds out it's
at the end of the file.

So, if you change your SeekOrigin.Current to SeekOrigin.Begin you'll
end up with

a
f

instead. It does mean you need to keep track of where you want to go to
rather than using SeekOrigin.Current, unfortunately - if you just want
to skip five characters, then using StreamReader.Read (remembering to
use the return value to find out how many characters you've actually
read) is probably easier.
 
Thanks a lot,Brian Brown and Jon Skeet!
So there's no way to use r.BaseStream.seek() cerrectly?
I used the seek() in another app like this
StreamReader r=new StreamReader(filename);
....
r.BaseStream.seek();
I hope to move file pointer,so seek() method is not fit here.
Could you tell me any other way to move file pointer in StreamReader?
 
Tiger said:
Thanks a lot,Brian Brown and Jon Skeet!
So there's no way to use r.BaseStream.seek() cerrectly?

There is, but using it with SeekOrigin.Current will give unexpected
results.
I used the seek() in another app like this
StreamReader r=new StreamReader(filename);
...
r.BaseStream.seek();
I hope to move file pointer,so seek() method is not fit here.
Could you tell me any other way to move file pointer in StreamReader?

Seeking is fine, so long as you know where you want to go to relative
to the start or end of the file.
 
Could you give me a example?

Jon Skeet said:
There is, but using it with SeekOrigin.Current will give unexpected
results.


Seeking is fine, so long as you know where you want to go to relative
to the start or end of the file.
 
Tiger said:
Could you give me a example?

As I said before, just change your code (including calling
DiscardBufferedData after the seek) to use

r.BaseStream.Seek(5, SeekOrigin.Begin)
 
I know!
Do you mean if I want to set the file pointer,I must remember the number of
the characters which have been read???
And I must use SeekOrigin.Begin?
 
Tiger said:
I know!
Do you mean if I want to set the file pointer,I must remember the number of
the characters which have been read???
And I must use SeekOrigin.Begin?

Potentially - and it gets harder if you have a multibyte character
encoding, too.

However, if you just want to skip a few characters, I'd use Read if I
were you.
 
Thank you very much,Jon!
you helped me a lot!

Jon Skeet said:
Potentially - and it gets harder if you have a multibyte character
encoding, too.

However, if you just want to skip a few characters, I'd use Read if I
were you.
 
Back
Top