locked
Read First and last line from text file RRS feed

  • Question

  • I have a text file whose location is d:\abc\abc.txt

    I have two text boxes whose names are txtFirstLine and txtLastLine respectively

    I want to read and display the first line of the textfile in txtFirstLine textbox

    and I want to read and display the last line of the textfile in txtLastLine textbox

    How can we do this in vb.net 2010

    Any help will be appreciated.

    Thanks

    Tuesday, February 5, 2013 4:34 PM

Answers

  • You can do it like this:

    Dim lines() As String = IO.File.ReadAllLines("d:\abc\abc.txt")
    txtFirstLine.Text = lines(0)
    txtLastLine.Text = lines(lines.Length - 1)
    The code reads the text file and creates an array of Strings with one line in each element of the array.  Then it copies the first line into one TextBox and the last line into the other.  Note that there is no way to find the last line of a text file without reading the whole file in some way.

    If your text file is hundreds of megabytes long, you might not want to read it all into memory at the same time. That seems unlikely, but if that is the case, let us know and we can show you how to just read one line at a time.
    • Edited by Blackwood Tuesday, February 5, 2013 4:55 PM
    • Proposed as answer by Cor Ligthert Tuesday, February 5, 2013 4:58 PM
    • Marked as answer by Youen Zen Friday, February 15, 2013 9:28 AM
    Tuesday, February 5, 2013 4:50 PM
  • Hi,

    No miracle solution, you'll have to read the whole file to reach the last line.

    You could load the entire file using File.ReadAllLines and then retrieve the First and Last one (FirstOrDefault and LastOrDefault if file can be empty)

    Alternatively you could use a StreamReader (or equivalent) and loop through the file.

    examples (I assume the File exists):

    ' first method
    Dim lines As String() = File.ReadAllLines(path)
    Dim firstLine As String = lines.First ' lines.FirstOrDefault
    Dim lastLine As String = lines.Last ' lines.LastOrDefault
    
    ' second method
    Dim firstLine As String = Nothing ' or String.Empty
    Dim lastLine As String = Nothing ' same here
    
    Using reader As New StreamReader(path)
        If Not reader.EndOfStream Then firstLine = reader.ReadLine
        Do Until reader.EndOfStream
            ' replace "previous" last line with "current" read line ,
            ' hence at end of loop lastLine will contain the "real" last line.
            lastLine = reader.ReadLine
        Loop
    End Using

    Typically the second approach is better if the file are large because you don't have to load the whole file in memory at once.

    • Proposed as answer by Cor Ligthert Tuesday, February 5, 2013 4:58 PM
    • Marked as answer by Youen Zen Friday, February 15, 2013 9:28 AM
    Tuesday, February 5, 2013 4:55 PM
  • I could test a little (my previous post was only based on my memory)

    And I remember of File.ReadLines (requires FW 4 or later)

    It's different of File.ReadAllLines because it evaluates lazily (it streams its data) and so can perform pretty well.

    Dim watch = Stopwatch.StartNew
    Dim lines = IO.File.ReadLines(path)
    
    Dim first = lines.FirstOrDefault
    Dim last = lines.LastOrDefault
    
    Console.WriteLine("{1}{0}{2}{0}{3}",
        Environment.NewLine, first, last, watch.Elapsed)
    

    With my computer for a file of approx 150 000 words (generated via Lorem Ipsum)I got a time of 7 milliseconds

    • Proposed as answer by JohnWein Tuesday, February 5, 2013 11:25 PM
    • Marked as answer by Youen Zen Friday, February 15, 2013 9:32 AM
    Tuesday, February 5, 2013 10:58 PM

All replies

  • You can do it like this:

    Dim lines() As String = IO.File.ReadAllLines("d:\abc\abc.txt")
    txtFirstLine.Text = lines(0)
    txtLastLine.Text = lines(lines.Length - 1)
    The code reads the text file and creates an array of Strings with one line in each element of the array.  Then it copies the first line into one TextBox and the last line into the other.  Note that there is no way to find the last line of a text file without reading the whole file in some way.

    If your text file is hundreds of megabytes long, you might not want to read it all into memory at the same time. That seems unlikely, but if that is the case, let us know and we can show you how to just read one line at a time.
    • Edited by Blackwood Tuesday, February 5, 2013 4:55 PM
    • Proposed as answer by Cor Ligthert Tuesday, February 5, 2013 4:58 PM
    • Marked as answer by Youen Zen Friday, February 15, 2013 9:28 AM
    Tuesday, February 5, 2013 4:50 PM
  • Hi,

    No miracle solution, you'll have to read the whole file to reach the last line.

    You could load the entire file using File.ReadAllLines and then retrieve the First and Last one (FirstOrDefault and LastOrDefault if file can be empty)

    Alternatively you could use a StreamReader (or equivalent) and loop through the file.

    examples (I assume the File exists):

    ' first method
    Dim lines As String() = File.ReadAllLines(path)
    Dim firstLine As String = lines.First ' lines.FirstOrDefault
    Dim lastLine As String = lines.Last ' lines.LastOrDefault
    
    ' second method
    Dim firstLine As String = Nothing ' or String.Empty
    Dim lastLine As String = Nothing ' same here
    
    Using reader As New StreamReader(path)
        If Not reader.EndOfStream Then firstLine = reader.ReadLine
        Do Until reader.EndOfStream
            ' replace "previous" last line with "current" read line ,
            ' hence at end of loop lastLine will contain the "real" last line.
            lastLine = reader.ReadLine
        Loop
    End Using

    Typically the second approach is better if the file are large because you don't have to load the whole file in memory at once.

    • Proposed as answer by Cor Ligthert Tuesday, February 5, 2013 4:58 PM
    • Marked as answer by Youen Zen Friday, February 15, 2013 9:28 AM
    Tuesday, February 5, 2013 4:55 PM
  • This will work without reading the entire file.

            Dim sr As IO.StreamReader = New IO.StreamReader(path)

            Dim fl As String = sr.ReadLine 'first line
            Dim ll As String 'last line
            Dim i As Integer = 2
            sr.DiscardBufferedData()
            Do
                If i <= sr.BaseStream.Length Then
                    sr.BaseStream.Seek(sr.BaseStream.Length - i, IO.SeekOrigin.Begin)
                    ll = sr.ReadToEnd
                    If ll.StartsWith(Environment.NewLine) Then
                        Exit Do
                    End If
                    i += 1
                Else
                    Throw New Exception("one line")
                End If
            Loop
            ll = ll.Replace(Environment.NewLine, "")
            sr.Close()


    "Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein

    Tuesday, February 5, 2013 5:38 PM
  • If it's a large text file, you can do it without reading the entire file using this code:

        Dim SR As New StreamReader(File.OpenRead("D:\abc\abc.txt"))
        txtFirstLine.Text = SR.ReadLine
        
    Dim LastLine As String, I, J As Integer, P As Long
        
    Do
          I = 0 : J += 128 : P = SR.BaseStream.Length - J
          
    If P < 0 Then P = 0
          SR.BaseStream.Position = P
          
    Do
            LastLine = SR.ReadLine : I += 1
          
    Loop Until SR.EndOfStream
        
    Loop Until I > 1 Or P = 0
        SR.Close()
        txtLastLine.Text = LastLine


    • Proposed as answer by Jonathan_SMS Friday, June 10, 2016 3:54 PM
    Tuesday, February 5, 2013 6:36 PM
  • If it's a large text file, you can do it without reading the entire file using this code:

        Dim SR As New StreamReader(File.OpenRead("D:\abc\abc.txt"))
        txtFirstLine.Text = SR.ReadLine
        
    Dim LastLine As String, I, J As Integer, P As Long
        
    Do
          I = 0 : J += 128 : P = SR.BaseStream.Length - J
          
    If P < 0 Then P = 0
          SR.BaseStream.Position = P
          
    Do
            LastLine = SR.ReadLine : I += 1
          
    Loop Until SR.EndOfStream
        
    Loop Until I > 1 Or P = 0
        SR.Close()
        txtLastLine.Text = LastLine



    Missing an EndIf somewhere.  I am guessing that this code is taking a SWAG at line length. 

    "Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein

    Tuesday, February 5, 2013 8:02 PM
  • "Missing an EndIf somewhere."

    Don't know where it would be.  There is only one explicit If statement in the code and it's a single line.

    Tuesday, February 5, 2013 8:09 PM
  • "Missing an EndIf somewhere."

    Don't know where it would be.  There is only one explicit If statement in the code and it's a single line.

    I see it now.

    I tested yours and mine with a file I have that is 900 lines long, average 72 characters per line.  Mine performed better.  It has to do with the position and what is in the buffer.  I had the same issue until I added the .DiscardBufferedData.


    "Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein

    Tuesday, February 5, 2013 9:55 PM
  • I don't remember much about the code other than it did what the OP asked.  I originally posted the code here:  reading last line of a text file
    Tuesday, February 5, 2013 10:45 PM
  • I could test a little (my previous post was only based on my memory)

    And I remember of File.ReadLines (requires FW 4 or later)

    It's different of File.ReadAllLines because it evaluates lazily (it streams its data) and so can perform pretty well.

    Dim watch = Stopwatch.StartNew
    Dim lines = IO.File.ReadLines(path)
    
    Dim first = lines.FirstOrDefault
    Dim last = lines.LastOrDefault
    
    Console.WriteLine("{1}{0}{2}{0}{3}",
        Environment.NewLine, first, last, watch.Elapsed)
    

    With my computer for a file of approx 150 000 words (generated via Lorem Ipsum)I got a time of 7 milliseconds

    • Proposed as answer by JohnWein Tuesday, February 5, 2013 11:25 PM
    • Marked as answer by Youen Zen Friday, February 15, 2013 9:32 AM
    Tuesday, February 5, 2013 10:58 PM
  • Most of the abstractions of the later frameworks have little use.  This is an example.  But it applies here.  Here it is in comprehensible format:

        Dim Lines As Collections.Generic.IEnumerable(Of String) = File.ReadLines("Test.txt")
        
    Dim Line0 As String = Lines.FirstOrDefault
        
    Dim LineN As String = Lines.LastOrDefault


    Tuesday, February 5, 2013 11:29 PM
  • Works for me when last line is needed:

     If e.KeyCode = Keys.Enter Then
    
                Dim TempTxt As String = TextBox1.Text
                Dim MatchTxt As String = TextBox1.Lines.Count
    
                TextBox1.Text = TempTxt
    
                For I = 0 To TextBox1.Lines.Count
                    For Each line As String In TextBox1.Lines
                        If I = MatchTxt Then
                            TextBox1.Text = Nothing
                            TextBox1.Text = TempTxt + vbNewLine & line & "   <<< It Works!!" 
                        End If
                    Next
                Next
    
            End If

    Sunday, October 18, 2015 12:34 PM