StreamReader reads an extra 1,024 bytes...

  • Thread starter Thread starter lord.zoltar
  • Start date Start date
L

lord.zoltar

Hi, I'm having some trouble with a StreamReader.
I use a System.IO.StreamReader to read a text file and then print it.
If the user has selected a range of pages starting past the first page,
I have to make the StreamReader jump to some point in the file.
To make the StreamReader jump to where it should be, I use the
following code:

fReader.BaseStream.Seek(fileBookmark + (Me.reportTextWidth *
linesPerPage * startPage), IO.SeekOrigin.Begin)

I've run this through the debugger, and the expression "fileBookmark +
(Me.reportTextWidth * linesPerPage * startPage)" seems to be
calculating the starting character correctly.
When I start reading the file, I use:

line = fReader.ReadLine()

....and this is where the problems occur!! I set a watch in the
debugger on fReader.BaseStream.Position. After the first operation (the
seek, shown above), fReader.BaseStream.Position is 2479. After the
ReadLine executes, fReader.BaseStream.Position is 3503, it has
increased by 1,024 Bytes! For all subsequent ReadLines,
fReader.BaseStream.Position does not change at all. Maybe I'm just not
quite understanding how the VB.NET StreamReader works... Does anyone
have an idea why this would be happening? Or maybe a better way to do
what I'm trying to do:
Jump to a position in a text file and read!
 
StreamReader is buffering the reads. When you ask it to read 1 byte it goes
ahead and gets 1024 to improve performance. The next byte you ask for
doesn't actually require a read operation, it just grabs the byte from the
buffer it's using.

Is this a problem, as in are you not getting the data you expect?
 
Peter said:
StreamReader is buffering the reads. When you ask it to read 1 byte it goes
ahead and gets 1024 to improve performance. The next byte you ask for
doesn't actually require a read operation, it just grabs the byte from the
buffer it's using.

Is this a problem, as in are you not getting the data you expect?
Exactly. Actually, it's weird: the page started printing at character
2353. I want it to start reading at EXACTLY 2479.
 
How are you creating your StreamReader object, through a c'tor and a filename
(getting the default FileStream object for the BaseStream property), or are
you using a constructor that takes a Stream object?

Seek/ReadLine should work fine, buffered IO should only read in new data
(and affecting the Position property) when it needs too.

You haven't specified what the actual problem is, other than Position isn't
changing as you expected (but as it should, regardless of what you expect).
If you're using ReadLine, how do you know what value to use for Seek?

You'll have to use something other than FileStream if you want unbuffered IO.
 
Exactly. Actually, it's weird: the page started printing at character
2353. I want it to start reading at EXACTLY 2479.

What character encoding are you using? If you're using any character
encoding which doesn't use a fixed number of bytes per character, you
basically can't skip to a desired character without reading the rest.
 
What character encoding are you using? If you're using any character
encoding which doesn't use a fixed number of bytes per character, you
basically can't skip to a desired character without reading the rest.

Err, it's whatever the default is. The file is a plain text ASCII file,
as far as I can tell. The same program that reads it also writes it,
and in all my text editors, it looks like plain ASCII text.
 
How are you creating your StreamReader object, through a c'tor and a filename
(getting the default FileStream object for the BaseStream property), or are
you using a constructor that takes a Stream object?

I'm doin' it like this:
fReader = New System.IO.StreamReader(Me.fileName)
Seek/ReadLine should work fine, buffered IO should only read in new data
(and affecting the Position property) when it needs too.

You haven't specified what the actual problem is, other than Position isn't
changing as you expected (but as it should, regardless of what you expect).
If you're using ReadLine, how do you know what value to use for Seek?

The exact problem is that I want to start reading (and then printing)
the file at character #2479, and it started at character #2353.
I calculate the position to seek to based on the starting page the user
requested in the print dialogue, the number of lines that will be
printed on a page, and the number of characters printed across the page
(yes it's ugly and awful and I was asked to do text reports that look
like this... /rolls eyes ;) ).
The specific code for the seeking looks like this:
fReader.BaseStream.Seek(fileBookmark + (Me.reportTextWidth *
linesPerPage * startPage), IO.SeekOrigin.Begin)
You'll have to use something other than FileStream if you want unbuffered IO.
I might be able to get rid of the text reports and use a proper
reporting system, in which case this whole problem may soon become
academic...:)
but it's not there yet.

What I thought I would try tomorrow would be to replace the ReadLine
with a combination of ReadBlock (since I will know exactly how many
characters per line) and Seek.
 
Err, it's whatever the default is. The file is a plain text ASCII file,
as far as I can tell. The same program that reads it also writes it,
and in all my text editors, it looks like plain ASCII text.

Okay, in that case you should be okay if you set the stream's position
(the Position property is easier to use than Seek btw - at least in my
view) and then call StreamReader.DiscardBufferedData().

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
Lord,

Are you sure there is no null byte in the string that you are reading?

Cor
 
Cor said:
Lord,

Are you sure there is no null byte in the string that you are reading?

Cor
Sorry in not responding for so long, the printing section suddenly
became low-priority as other stuff came up. It still will have to be
done so I will still have to try all the suggestions here, but maybe
not as soon as I had liked :(

Cor, I was taking newline characters into account, 1 for each line.
Where would a nullbyte be? I would have only expected it at the end of
the file.
 
Back
Top