Nianios
Nianios

Reputation: 1426

I want to read the last 400 lines from a txt file

I know how to do it in VB.Net but not an idea in vb6.
What I what to achieve is to avoid reading the whole file.
Is that possible?

Upvotes: 1

Views: 918

Answers (3)

Mark Bertenshaw
Mark Bertenshaw

Reputation: 5689

The following is my take on this. This is more efficient than the previous two answers if you have a very large file, since we don't have to store the entire file in memory.

Option Explicit

Private Sub Command_Click()

    Dim asLines()                           As String

    asLines() = LoadLastLinesInFile("C:\Program Files (x86)\VMware\VMware Workstation\open_source_licenses.txt", 400)

End Sub

Private Function LoadLastLinesInFile(ByRef the_sFileName As String, ByVal the_nLineCount As Long) As String()

    Dim nFileNo                             As Integer
    Dim asLines()                           As String
    Dim asLinesCopy()                       As String
    Dim bBufferWrapped                      As Boolean
    Dim nLineNo                             As Long
    Dim nLastLineNo                         As Long
    Dim nNewLineNo                          As Long
    Dim nErrNumber                          As Long
    Dim sErrSource                          As String
    Dim sErrDescription                     As String

    On Error GoTo ErrorHandler

    nFileNo = FreeFile

    Open the_sFileName For Input As #nFileNo

    On Error GoTo ErrorHandler_FileOpened

    ' Size our buffer to the number of specified lines.
    ReDim asLines(0 To the_nLineCount - 1)
    nLineNo = 0

    ' Read all lines until the end of the file.
    Do Until EOF(nFileNo)
        Line Input #nFileNo, asLines(nLineNo)
        nLineNo = nLineNo + 1
        ' Check to see whether we have got to the end of the string array.
        If nLineNo = the_nLineCount Then
            ' In which case, flag that we did so, and wrap back to the beginning.
            bBufferWrapped = True
            nLineNo = 0
        End If
    Loop

    Close nFileNo

    On Error GoTo ErrorHandler

    ' Were there more lines than we had array space?
    If bBufferWrapped Then
        ' Create a new string array, and copy the bottom section of the previous array into it, followed
        ' by the top of the previous array.
        ReDim asLinesCopy(0 To the_nLineCount - 1)
        nLastLineNo = nLineNo
        nNewLineNo = 0
        For nLineNo = nLastLineNo + 1 To the_nLineCount - 1
            asLinesCopy(nNewLineNo) = asLines(nLineNo)
            nNewLineNo = nNewLineNo + 1
        Next nLineNo
        For nLineNo = 0 To nLastLineNo
            asLinesCopy(nNewLineNo) = asLines(nLineNo)
            nNewLineNo = nNewLineNo + 1
        Next nLineNo
        ' Return the new array.
        LoadLastLinesInFile = asLinesCopy()
    Else
        ' Simply resize down the array, and return it.
        ReDim Preserve asLines(0 To nLineNo)
        LoadLastLinesInFile = asLines()
    End If

Exit Function

ErrorHandler_FileOpened:
    ' If an error occurred whilst reading the file, we must ensure that the file is closed
    ' before reraising the error. We have to backup and restore the error object.
    nErrNumber = Err.Number
    sErrSource = Err.Source
    sErrDescription = Err.Description
    Close #nFileNo
    Err.Raise nErrNumber, sErrSource, sErrDescription

ErrorHandler:
    Err.Raise Err.Number, Err.Source, Err.Description
End Function

Upvotes: 0

George
George

Reputation: 2213

Cometbill has a good answer.

To open file for Random access:

Open filename For Random Access Read As #filenumber Len = reclength

To get the length of the file in Bytes:

FileLen(ByVal PathName As String) As Long

To read from Random access file:

Get [#]filenumber,<[recnumber]>,<varname>

IMPORTANT: the <varname> from the Get function must be a fixed length string Dim varname as String * 1, otherwise it will error out with Bad record length (Error 59) if the variable is declared as a variable length string like this Dim varname as String

EDIT:

Just wanted to point out that in Dim varname as String * 1 you are defining a fixed length string and the length is 1. This is if you wish to use the read-1-byte-backwards approach. If your file has fixed length records, there is no need to go 1 byte at a time, you can read a record at a time (don't forget to add 2 bytes for carriage return and new line feed). In the latter case, you would define Dim varname as String * X where X is the record length + 2. Then a simple loop going backwards 400 times or untill reaching the beginning of the file.

Upvotes: 1

cometbill
cometbill

Reputation: 1619

You could open the file using Random access. Work your way backward a byte at a time, counting the number of carriage return line feed character pairs. Store each line in an array, or something similar, and when you've read your 400 lines, stop.

Upvotes: 1

Related Questions