Results 1 to 16 of 16

Thread: Tail a log file (text file)

  1. #1

    Thread Starter
    New Member
    Join Date
    Oct 2002
    Location
    Sacramento, CA USA
    Posts
    6

    Tail a log file (text file)

    My question is how would I go about monitoring the last line of a log file and displaying it in a txtfield? Here is the scenario:

    I have an application running that sends some events to a log file it keeps. Keep in mind that this file is opened by the application. I would like to read the last line of the log file and print that in my app, and then when ever it is updated print the new update.

    Additionally a more advanced way would be the last 5 lines of the log file to get a semi-history. An even more advanced way would be to have a scrolling function to track all of it if the user needed to see if they'd missed something.

    thank you

  2. #2
    Frenzied Member DevGrp's Avatar
    Join Date
    Nov 2001
    Location
    Charlotte, NC
    Posts
    1,256
    Why dont you just load the log file into the textbox? Easiest solution. If you are going to do that, make sure the textbox is set to multiline.
    Dont gain the world and lose your soul

  3. #3

    Thread Starter
    New Member
    Join Date
    Oct 2002
    Location
    Sacramento, CA USA
    Posts
    6
    That partially works, but how would I get it to update as the log updated. I'd rather not keep passing the entire file every time. The log gets rather large, it's for one of our security devices.

    So my question is partially answered but now I need to know how to keep updating the entries as the log is updated.

    Thanks again.

  4. #4
    Fanatic Member
    Join Date
    Sep 2002
    Posts
    518
    Try something like this:
    Code:
    Imports System.IO
    
    Public Class Form1
        Inherits System.Windows.Forms.Form
    
    #Region " Windows Form Designer generated code "
    
        Public Sub New()
            MyBase.New()
    
            'This call is required by the Windows Form Designer.
            InitializeComponent()
    
            'Add any initialization after the InitializeComponent() call
    
        End Sub
    
        'Form overrides dispose to clean up the component list.
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If Not (components Is Nothing) Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub
    
        'Required by the Windows Form Designer
        Private components As System.ComponentModel.IContainer
    
        'NOTE: The following procedure is required by the Windows Form Designer
        'It can be modified using the Windows Form Designer.  
        'Do not modify it using the code editor.
        Friend WithEvents btnTail As System.Windows.Forms.Button
        Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
        Friend WithEvents Label1 As System.Windows.Forms.Label
        Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.btnTail = New System.Windows.Forms.Button()
            Me.TextBox1 = New System.Windows.Forms.TextBox()
            Me.Label1 = New System.Windows.Forms.Label()
            Me.TextBox2 = New System.Windows.Forms.TextBox()
            Me.SuspendLayout()
            '
            'btnTail
            '
            Me.btnTail.Location = New System.Drawing.Point(272, 464)
            Me.btnTail.Name = "btnTail"
            Me.btnTail.TabIndex = 0
            Me.btnTail.Text = "Tail"
            '
            'TextBox1
            '
            Me.TextBox1.Location = New System.Drawing.Point(64, 24)
            Me.TextBox1.Name = "TextBox1"
            Me.TextBox1.Size = New System.Drawing.Size(552, 20)
            Me.TextBox1.TabIndex = 1
            Me.TextBox1.Text = ""
            '
            'Label1
            '
            Me.Label1.Location = New System.Drawing.Point(0, 24)
            Me.Label1.Name = "Label1"
            Me.Label1.Size = New System.Drawing.Size(64, 32)
            Me.Label1.TabIndex = 2
            Me.Label1.Text = "Filename and path:"
            '
            'TextBox2
            '
            Me.TextBox2.Location = New System.Drawing.Point(8, 72)
            Me.TextBox2.Multiline = True
            Me.TextBox2.Name = "TextBox2"
            Me.TextBox2.ReadOnly = True
            Me.TextBox2.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
            Me.TextBox2.Size = New System.Drawing.Size(608, 376)
            Me.TextBox2.TabIndex = 3
            Me.TextBox2.Text = ""
            '
            'Form1
            '
            Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
            Me.ClientSize = New System.Drawing.Size(624, 501)
            Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.TextBox2, Me.Label1, Me.TextBox1, Me.btnTail})
            Me.Name = "Form1"
            Me.Text = "Form1"
            Me.ResumeLayout(False)
    
        End Sub
    
    #End Region
    
        Private Sub btnTail_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTail.Click
            Dim SRead As Stream
            Try
                SRead = File.OpenRead(TextBox1.Text)
                Dim SrRead As StreamReader = New StreamReader(SRead, System.Text.Encoding.ASCII)
                ' set the file pointer to the beginning
                SrRead.BaseStream.Seek(0, SeekOrigin.Begin)
                SrRead.BaseStream.Position = SrRead.BaseStream.Length - 500
                Dim buffer(500) As Char
                SrRead.Read(buffer, 0, (SrRead.BaseStream.Length - SrRead.BaseStream.Position))
                TextBox2.Text = buffer
                SrRead.DiscardBufferedData()
                SrRead.Close()
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Sub
    End Class
    although you may want to add some code to trap for files less than 500 bytes, or of course you may want to read more than 500 bytes from the end. Hope this helps.

  5. #5
    Fanatic Member
    Join Date
    Sep 2002
    Posts
    518
    Originally posted by crunnluadh
    That partially works, but how would I get it to update as the log updated.
    Take a look at the FileSystemWatcher:

    ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfSystemIOFileSystemWatcherClassTopic.htm

    prolly you can tack one onto the tail code above pretty easy

  6. #6
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    The FileSystemWatcher is definately the way to go for this, here is an example. Sorry I forgot to comment it.

  7. #7
    Frenzied Member DevGrp's Avatar
    Join Date
    Nov 2001
    Location
    Charlotte, NC
    Posts
    1,256
    The example that Edneeis provided should get you started.

    Good work Edneeis.
    Dont gain the world and lose your soul

  8. #8

    Thread Starter
    New Member
    Join Date
    Oct 2002
    Location
    Sacramento, CA USA
    Posts
    6

    Thank you to everyone

    Thank you all for the great advice and timely . It was a rather important side project a few of us are tackling. Thanks again.

  9. #9
    Fanatic Member
    Join Date
    Sep 2002
    Posts
    518
    Went ahead and added the tail code instead of reading the whole file
    Attached Files Attached Files

  10. #10
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    I forgot to scroll the textbox to the bottom, so here is that part:

    VB Code:
    1. 'scroll to the bottom
    2.             txtLog.SelectionStart = txtLog.Text.Length
    3.             txtLog.ScrollToCaret()

    And if you want to just grab a certain number of 'lines' from the log then you can use this. I used a Queue to just grab the bottom lines other than that it is a lot like Slow_Leaners that grabs the end in bytes.

    VB Code:
    1. Private Sub UpdateText(ByVal sender As System.Object, ByVal e As FileSystemEventArgs)
    2.         Try
    3.             Dim SRead As Stream
    4.             'open file
    5.             SRead = File.OpenRead("Log.txt")
    6.             Dim SrRead As StreamReader = New StreamReader(SRead, System.Text.Encoding.ASCII)
    7.             'setup queue
    8.             Dim q As New Queue()
    9.             'read lines into que and only keep the last lines upto the value of txtLinesToTail
    10.             While (SrRead.Peek() > -1)
    11.                 Dim Buffer As String = SrRead.ReadLine()
    12.                 'add line to queue
    13.                 q.Enqueue(Buffer)
    14.                 'ditch any lines more than needed
    15.                 If q.Count > CInt(txtLinesToTail.Text) Then q.Dequeue()
    16.             End While
    17.             'transfer the queue contents to the textbox
    18.             Dim line As String
    19.             txtLog.Text = String.Empty
    20.             For Each line In q
    21.                 txtLog.Text &= String.Concat(line, ControlChars.NewLine)
    22.             Next
    23.             'scroll to the bottom
    24.             txtLog.SelectionStart = txtLog.Text.Length
    25.             txtLog.ScrollToCaret()
    26.             'close the file
    27.             SrRead.Close()
    28.         Catch ex As Exception
    29.             'show error
    30.             MsgBox(ex.Message)
    31.         End Try
    32.     End Sub
    33.  
    34.     Private Sub txtLinesToTail_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtLinesToTail.TextChanged
    35.         'update with new line count
    36.         UpdateText(Me, Nothing)
    37.     End Sub
    Last edited by Edneeis; Oct 5th, 2002 at 07:41 PM.

  11. #11
    Fanatic Member
    Join Date
    Sep 2002
    Posts
    518
    I may be reading this wrong but:
    Code:
                While (SrRead.Peek() > -1)
                    Dim Buffer As String = SrRead.ReadLine()
                    'add line to queue
                    q.Enqueue(Buffer)
                    'ditch any lines more than needed
                    If q.Count > CInt(txtLinesToTail.Text) Then q.Dequeue()
                End While
    Doesn't that actually read the entire file? What if the file's 10mb or more?

  12. #12
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    That is true but there is no way to tell how long a line is (that I know of). So you have to read it all in and then only keep the last x amount of lines. Although I thought yours was an excellent example of doing it conversatively with bytes.

  13. #13
    Fanatic Member
    Join Date
    Sep 2002
    Posts
    518
    ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfSystemIOFileInfoClassLengthTopic.htm

    So if you wanted to be extra careful, before you move the .BaseStream.Position to a certain position you'd check to see how long the file was (I believe FileInfo.Length returns bytes) and then trap against that to keep an exception from happening. Right?
    ...
    duh woops how long a LINE is eh? As in how many lines in a given file? Yeah I see what you mean. :/

  14. #14
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    Especially since it appears that the ReadLine reads the text until it encounters a CrLf character so each line is not the same size.

  15. #15
    Fanatic Member
    Join Date
    Sep 2002
    Posts
    518
    Yeah I've been working with reading delimited text files rather a lot lately so I figured ReadLine was right out for this problem, for just the reason you say.

  16. #16

    Thread Starter
    New Member
    Join Date
    Oct 2002
    Location
    Sacramento, CA USA
    Posts
    6

    Thanks everyone

    Thank you to everyone that responded and contributed code. We got it working and for the moment correctly . Thanks again.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width