473,396 Members | 1,871 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Reading text file, bottom up?

I have tab delimited text file which gets populated on daily basis via
automated process. New entry is written at the bottom. I need to create a
utility which makes a copy of this file with 10 most recent entries.

When I read line using StreamReader object it starts from the top, so
looping though lines and keeping track of the line is not helpful. Is there
anyway to start reading from the bottom or if anyone could suggest some other
way???

Thanks

Jul 21 '05 #1
14 4442
Job Lot <Jo****@discussions.microsoft.com> wrote:
I have tab delimited text file which gets populated on daily basis via
automated process. New entry is written at the bottom. I need to create a
utility which makes a copy of this file with 10 most recent entries.

When I read line using StreamReader object it starts from the top, so
looping though lines and keeping track of the line is not helpful. Is there
anyway to start reading from the bottom or if anyone could suggest some other
way???


Reading from the end of a file is very difficult in a general case,
partly because you'd have to keep either seeking backwards for every
byte you read, or you'd have to keep a buffer and read (say) the last
10 bytes, then seek to the start of the 10 bytes before that, etc.

You then have the added problem of character encodings - it's not so
bad if you're using a fixed-width character encoding, but with
something like UTF-8, you have to work out where the start of the
previous character is, etc.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #2
perhaps this will help:
http://dotnetjunkies.com/WebLog/john.../05/41694.aspx

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
"Job Lot" <Jo****@discussions.microsoft.com> wrote in message
news:72**********************************@microsof t.com...
I have tab delimited text file which gets populated on daily basis via
automated process. New entry is written at the bottom. I need to create a
utility which makes a copy of this file with 10 most recent entries.

When I read line using StreamReader object it starts from the top, so
looping though lines and keeping track of the line is not helpful. Is
there
anyway to start reading from the bottom or if anyone could suggest some
other
way???

Thanks

Jul 21 '05 #3
Job,

Just an idea,

Would reading it in an arraylist using insert(0,line), while you remove when
that exist everytime row 10 be an idea?

Cor
Jul 21 '05 #4
Why not read every line into a stack. Then when the file is done, the
last ten items will be at the top of the stack. Just pop 10 times and
you're done.

Jul 21 '05 #5
On Tue, 15 Feb 2005 21:27:02 -0800, "Job Lot" <Jo****@discussions.microsoft.com> wrote:

¤ I have tab delimited text file which gets populated on daily basis via
¤ automated process. New entry is written at the bottom. I need to create a
¤ utility which makes a copy of this file with 10 most recent entries.
¤
¤ When I read line using StreamReader object it starts from the top, so
¤ looping though lines and keeping track of the line is not helpful. Is there
¤ anyway to start reading from the bottom or if anyone could suggest some other
¤ way???

Is there a column in the file which corresponds to the order in which the entries are written (such
as a date or sequence number)?
Paul ~~~ pc******@ameritech.net
Microsoft MVP (Visual Basic)
Jul 21 '05 #6
Nick Malik [Microsoft] <ni*******@hotmail.nospam.com> wrote:
perhaps this will help:
http://dotnetjunkies.com/WebLog/john.../05/41694.aspx


Unfortunately that reads the whole file, which I assume is something
the OP doesn't want to do.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #7
Thanks everyone.

Paul, there is no such column which corresponds to the order.

Patrick A, reading to stack seems to fit the bill. But I really don’t know
how to read line to stack?
"Patrick A" wrote:
Why not read every line into a stack. Then when the file is done, the
last ten items will be at the top of the stack. Just pop 10 times and
you're done.

Jul 21 '05 #8
It doesn't actually. The code displayed in the blog is out of date.

Here's the code I use, which seems to work but may not be perfect:

public void FindLastPosition()
{
FileStream stream = new FileStream(filename, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
int charSize = System.Text.Encoding.Default.GetByteCount(" ");
int count = 0;
stream.Seek(0, SeekOrigin.End);
long pos = stream.Position;
while (pos>0 && count<lines)
{
pos -= charSize;
stream.Seek(pos, SeekOrigin.Begin);
if ((char)stream.ReadByte()=='\r') count++;
}
stream.Seek(pos<1 ? 0 : pos, SeekOrigin.Begin);

filePos = stream.Position;
stream.Close();
}

Hope that helps.

---
John Wood
http://dotnetjunkies.com/weblog/johnwood

"Jon Skeet [C# MVP]" wrote:
Nick Malik [Microsoft] <ni*******@hotmail.nospam.com> wrote:
perhaps this will help:
http://dotnetjunkies.com/WebLog/john.../05/41694.aspx


Unfortunately that reads the whole file, which I assume is something
the OP doesn't want to do.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Jul 21 '05 #9
<=?Utf-8?B?Sm9obiBXb29k?= <John Wo**@discussions.microsoft.com>>
wrote:
It doesn't actually. The code displayed in the blog is out of date.
Then "it" does - where "it" is the code Nick posted a link to!
Here's the code I use, which seems to work but may not be perfect:


That'll work on ASCII-like files with a single byte per character and a
line terminator which is or starts with carriage return. It won't work
reliably on any other type of file:

1) It assumes the file is in Encoding.Default
2) It assumes a fixed character size for seeking, which is invalid for
encodings such as UTF-8
3) It assumes a single byte per character when reading a byte, and
then assumes that the file is effectively ASCII by assuming that
a byte of 13 means carriage return. There are many characters in
Encoding.Unicode (for example) which have 13 as one of their bytes
4) It assumes that '\r' is part of the line terminator, which won't
be true for a lot of files generated on Unix

There are ways to fix some of these problems (and to make it perform
better by reading into a buffer rather than seeking for each byte) but
it's far from trivial given encodings like UTF-8.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #10
Well sorry, "it" was actually the download on the page I thought!

Anyway you do make some very valid points, but it should work ok for ascii.

Regarding the "reading into a buffer instead", it seems to perform quite
well because the stream seems to be buffered anyway (assuming it's not
forward only buffering).

I'd be interested in finding out how the "real" tail handles different
encodings...

"Jon Skeet [C# MVP]" wrote:
<=?Utf-8?B?Sm9obiBXb29k?= <John Wo**@discussions.microsoft.com>>
wrote:
It doesn't actually. The code displayed in the blog is out of date.


Then "it" does - where "it" is the code Nick posted a link to!
Here's the code I use, which seems to work but may not be perfect:


That'll work on ASCII-like files with a single byte per character and a
line terminator which is or starts with carriage return. It won't work
reliably on any other type of file:

1) It assumes the file is in Encoding.Default
2) It assumes a fixed character size for seeking, which is invalid for
encodings such as UTF-8
3) It assumes a single byte per character when reading a byte, and
then assumes that the file is effectively ASCII by assuming that
a byte of 13 means carriage return. There are many characters in
Encoding.Unicode (for example) which have 13 as one of their bytes
4) It assumes that '\r' is part of the line terminator, which won't
be true for a lot of files generated on Unix

There are ways to fix some of these problems (and to make it perform
better by reading into a buffer rather than seeking for each byte) but
it's far from trivial given encodings like UTF-8.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Jul 21 '05 #11
John Wood <Jo******@discussions.microsoft.com> wrote:
Well sorry, "it" was actually the download on the page I thought!
Unfortunately it's not clear from the page that the download will be
any different from the code which is prominently displayed to start
with. Could I suggest that you either change the blog entry to have the
new code, or add something (at the top, in bold) to make it clear it's
not the most recent version?
Anyway you do make some very valid points, but it should work ok for ascii.
True.
Regarding the "reading into a buffer instead", it seems to perform quite
well because the stream seems to be buffered anyway (assuming it's not
forward only buffering).

I'd be interested in finding out how the "real" tail handles different
encodings...


I have a sneaking suspicion it might not - or at least, older versions
wouldn't. Given enough work, most character encodings could be
supported, but you need more knowledge of them than the .NET framework
gives you. (For instance, you very fairly easily tell when you've got
to the first byte of a UTF-8 sequence, but you'd need to specifically
know that you're dealing with UTF-8 - the Encoding doesn't help you.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #12
This block outputs the last ten lines in a www log file:
Stack s = new Stack();
string filename =
@"C:\WINDOWS\system32\Logfiles\W3SVC1\ex050216.log ";

// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader(filename))
{
String line;
while ((line = sr.ReadLine()) != null)
{
s.Push(line);
}
}

string output;
for (int i = 0; i < 10; i++)
{
output = (string)s.Pop();
Debug.WriteLine(output);

}

Jul 21 '05 #13
Patrick A <pw*******@gmail.com> wrote:
This block outputs the last ten lines in a www log file:


<snip>

Yes, but again, it requires reading in the whole file, which I believe
the OP doesn't want to do. (If you're going to do that, using an
ArrayList would get a more flexible collection at the end of it - it's
easy to get the last 10 lines from an ArrayList, but it's hard to get
random access to a Stack, which would often be useful.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #14
just a thought but have you considered using an array as mentioned by Jon
Skeet?
i dont understand his assumption of not wanting to read the whole file as
you've made no mention of said requirement.

just a suggestion but if you have Visual Basic.net you might try this:

Option Explicit On
Option Strict On
Imports System.io
Module Module1
Public Sub main()
Dim lines As String()
Try
Dim sr As StreamReader = New StreamReader("yourfilehere.log",
System.Text.Encoding.ASCII) ' assuming ascii
Dim data As String
data = Replace(sr.ReadToEnd(), ControlChars.CrLf,
ControlChars.Cr) 'assuming the tab delimited lines terminated by crlf
lines = data.Split(CChar(ControlChars.Cr))
sr.Close()
Catch E As Exception
' Let the user know what went wrong.
Console.WriteLine("The log file could not be read:")
Console.WriteLine(E.Message)
Exit Sub
End Try
Try
Dim sw As StreamWriter = New StreamWriter("copy of
yourfilenamehere.log", False, System.Text.Encoding.ASCII) 'assuming ascii
If UBound(lines, 1) >= 10 Then
Dim i As Integer
For i = 1 To 10
sw.WriteLine(lines(UBound(lines, 1) - i))
Next
Else
Dim i As Integer
For i = 1 To UBound(lines, 1)
sw.WriteLine(lines(UBound(lines, 1) - i))
Next
End If
sw.Close()
Catch E As Exception
Console.WriteLine("Something broke O_o?")
Console.WriteLine(E.Message)
End Try
End Sub

End Module

"Job Lot" wrote:
I have tab delimited text file which gets populated on daily basis via
automated process. New entry is written at the bottom. I need to create a
utility which makes a copy of this file with 10 most recent entries.

When I read line using StreamReader object it starts from the top, so
looping though lines and keeping track of the line is not helpful. Is there
anyway to start reading from the bottom or if anyone could suggest some other
way???

Thanks

Jul 21 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: David Gray | last post by:
Greetings all, I'm working on a program that allows a user to enter notes in a multiline textbox. I would like to be able to read the contents of the textbox (as records - one per line) and...
18
by: Michael | last post by:
Hi, I moved to c++ from c, and wanted to know what the best way to read data from files is in c++. Any thoughts? fscanf() is possible but fairly painful! Regards Michael
6
by: tkpmep | last post by:
I have a text file with many hundreds of lines of data. The data of interest to me, however, resides at the bottom of the file, in the last 20 lines. Right now, I read the entire file and discard...
50
by: Michael Mair | last post by:
Cheerio, I would appreciate opinions on the following: Given the task to read a _complete_ text file into a string: What is the "best" way to do it? Handling the buffer is not the problem...
5
by: Scott M. Lyon | last post by:
I've just discovered a bug in some code I wrote a little while ago, and I need you guys' help to fix it. My program imports data from a standard Excel Spreadsheet (just with specific column...
14
by: Job Lot | last post by:
I have tab delimited text file which gets populated on daily basis via automated process. New entry is written at the bottom. I need to create a utility which makes a copy of this file with 10 most...
1
by: paulnightingale | last post by:
Hi I've got a ticker tape that is written in Java Script 1.2 which displays text that has to be currently changed in the program code. What I want to do is to find the bit of javascript to get the...
9
by: szclark | last post by:
Hello, I am trying to extract information from a file I have so that I can answer some questions on it, the problem I'm having is that it is returning back mostly gibberish and I really don't know...
1
by: akalmand | last post by:
Hi there, I am writing a code to read some data from the text files. The number of text files is not fixed and could be more that 15. the length of each file is large... close to 100,000 on an...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.