Reading a file backwards in C#

G

Guest

I have a log file that puts the most recent record at the bottom of the file. Each line is delimited by a \r\n

Does anyone know how to seek to the end of the file and start reading backwards?
 
R

Rick Sawtell

Not sure about that, but you could always read the file into an array
row-by-row and then use a loop to read it backwards.


Rick Sawtell
MCT, MCSD, MCDBA



Neil Patel said:
I have a log file that puts the most recent record at the bottom of the
file. Each line is delimited by a \r\n
Does anyone know how to seek to the end of the file and start reading
backwards?
 
S

Shakir Hussain

Couple of ways to do that.

Method 1:

//initialize streamreader
StreamReader myStream= new StreamReader(@"c:\myfile.txt");
//seek file pointer to end
myStream.BaseStream.Seek(1024,SeekOrigin.End);

//intialize array of size 1024
char [] arr = new char[1024];
//loop now and read backwards
While(myStream.BaseStream.Position > 0)
{
arr.Initialize();
//Move back 1024 bytes (for better control)
myStream.BaseStream.Seek(1024,SeekOrigin.Current);
//read 1024 bytes.
int bytesRead = myStream.Read(arr,0,1024);

}

Method:2

//initialize streamreader
StreamReader myStream = new StreamReader(@"c:\myfile.txt");
//read all the contents and store in string
string WholeFileString=myStream.ReadToEnd();
//convert to array
char []strArray = WholeFileString.ToCharArray();
//reverse the array
Array.Reverse(strArray);
//again convert to string
string newStr = new string(strArray);
//specify the split array (Note \r\n must be specified reverse becoz
string is reverse
char [] split = new char[2];
split[0] = '\n';
split[1] = '\r';
//receive the string array after spliting
string [] Lines = newStr.Split(split);

lines[0] = ; //last line of the file
lines[lines.Length-1] = ; //first line of the file

--
Shak
(Houston)


Neil Patel said:
I have a log file that puts the most recent record at the bottom of the
file. Each line is delimited by a \r\n
Does anyone know how to seek to the end of the file and start reading
backwards?
 
S

Shakir Hussain

Sorry some typos
myStream.BaseStream.Seek(1024,SeekOrigin.End);

this must be

myStream.BaseStream.Seek(0,SeekOrigin.End);
myStream.BaseStream.Seek(1024,SeekOrigin.Current);

this must be
myStream.BaseStream.Seek(-1024,SeekOrigin.Current);


--
Shak
(Houston)



Shakir Hussain said:
Couple of ways to do that.

Method 1:

//initialize streamreader
StreamReader myStream= new StreamReader(@"c:\myfile.txt");
//seek file pointer to end
myStream.BaseStream.Seek(1024,SeekOrigin.End);

//intialize array of size 1024
char [] arr = new char[1024];
//loop now and read backwards
While(myStream.BaseStream.Position > 0)
{
arr.Initialize();
//Move back 1024 bytes (for better control)
myStream.BaseStream.Seek(1024,SeekOrigin.Current);
//read 1024 bytes.
int bytesRead = myStream.Read(arr,0,1024);

}

Method:2

//initialize streamreader
StreamReader myStream = new StreamReader(@"c:\myfile.txt");
//read all the contents and store in string
string WholeFileString=myStream.ReadToEnd();
//convert to array
char []strArray = WholeFileString.ToCharArray();
//reverse the array
Array.Reverse(strArray);
//again convert to string
string newStr = new string(strArray);
//specify the split array (Note \r\n must be specified reverse becoz
string is reverse
char [] split = new char[2];
split[0] = '\n';
split[1] = '\r';
//receive the string array after spliting
string [] Lines = newStr.Split(split);

lines[0] = ; //last line of the file
lines[lines.Length-1] = ; //first line of the file

--
Shak
(Houston)


Neil Patel said:
I have a log file that puts the most recent record at the bottom of the
file. Each line is delimited by a \r\n
Does anyone know how to seek to the end of the file and start reading
backwards?
 
J

Jon Skeet [C# MVP]

Shakir Hussain said:
Couple of ways to do that.

Method 1:

//initialize streamreader
StreamReader myStream= new StreamReader(@"c:\myfile.txt");
//seek file pointer to end
myStream.BaseStream.Seek(1024,SeekOrigin.End);

//intialize array of size 1024
char [] arr = new char[1024];
//loop now and read backwards
While(myStream.BaseStream.Position > 0)
{
arr.Initialize();
//Move back 1024 bytes (for better control)
myStream.BaseStream.Seek(1024,SeekOrigin.Current);
//read 1024 bytes.
int bytesRead = myStream.Read(arr,0,1024);

}

Note that you've got a bit of confusion here between bytes and
characters - a StreamReader returns the number of *characters* read,
not bytes... and that introduces another problem. There's nothing to
say that moving backwards 1024 bytes will even put you at the start of
a character - it could be in the middle of a multi-byte character.

You also need to discard the StreamReader's buffer after repositioning.

Also, the first parameter to Seek should be -1024, not 1024, otherwise
it's moving forwards not backwards.

Finally, moving back 1024 bytes doesn't mean you'll move back 1024
characters, so the code above could mean reading some characters twice.
Method:2

//initialize streamreader
StreamReader myStream = new StreamReader(@"c:\myfile.txt");
//read all the contents and store in string
string WholeFileString=myStream.ReadToEnd();
//convert to array
char []strArray = WholeFileString.ToCharArray();
//reverse the array
Array.Reverse(strArray);
//again convert to string
string newStr = new string(strArray);
//specify the split array (Note \r\n must be specified reverse becoz
string is reverse
char [] split = new char[2];
split[0] = '\n';
split[1] = '\r';
//receive the string array after spliting
string [] Lines = newStr.Split(split);

lines[0] = ; //last line of the file
lines[lines.Length-1] = ; //first line of the file

That gives every line of the file reversed as well, which probably
isn't desired. I'd suggest:

ArrayList list = new ArrayList();
using (StreamReader reader = new StreamReader(@"c:\myfile.txt")
{
string line;
while ( (line=reader.ReadLine()) != null)
{
list.Add(line);
}
}
list.Reverse();

That gives you an ArrayList of each line of the file, starting from the
end. It probably doesn't help the OP, however, as I'd assume that the
idea is to avoid having to read the whole file.
 
J

Jon Skeet [C# MVP]

<"=?Utf-8?B?TmVpbCBQYXRlbA==?=" <Neil
I have a log file that puts the most recent record at the bottom of
the file. Each line is delimited by a \r\n

Does anyone know how to seek to the end of the file and start reading
backwards?

It would be possible to have a type of stream which wrapped another
stream (a seekable one) and read it backwards. It would buffer a chunk
at a time, and offer up the contents of that buffer backwards. It
wouldn't be particularly hard to write, so long as you kept everything
nice and simple.

What's much harder is writing an Encoding which is capable of taking
that backwards stream and converting it into a backwards sequence of
characters. In some encodings it may even be impossible. For any
encoding with a fixed size, it's pretty easy. (In fact, it would be
possible to write an encoding which, given another encoding and the
fixed number of bytes per character used by that encoding, created a
backwards encoding for it.)

For UTF-8 it's possible, as you can detect when a character ends.
(Either the top two bits are set or the top bit is unset.) It's non-
trivial to write though.

The main point is you'd need to do this for each encoding you're
interested in - which encoding is the log file in? I could probably be
persuaded to help out with the backwards stream and a single encoding,
but I'm not going to start writing multiple encodings on the off-chance
that I write the one that's useful to you :)
 
G

Guest

or push each row onto a stack, then you pop them off...

hth guy

(assuming you have enough ram to read the whole file)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top