0

any idea how to read last or two last lines of a file containing about 30 lines with \n with focus on performance speed?

EDIT: something faster than:

string[] splitedArray= input.Split('\n');
string lastLine = splitedArray[splitedArray.Length-1];

Using c#

cuongle
  • 74,024
  • 28
  • 151
  • 206
Martin Ch
  • 1,337
  • 4
  • 21
  • 42
  • Almost a duplicate: [how-to-read-a-text-file-reversely-with-iterator-in-c-sharp?](http://stackoverflow.com/questions/452902/how-to-read-a-text-file-reversely-with-iterator-in-c-sharp?) – nawfal May 26 '14 at 09:36

4 Answers4

11

from the top of my head

string lastline = input.Substring(
   input.LastIndexOf('\n'));
rene
  • 41,474
  • 78
  • 114
  • 152
  • 1
    `string lastline = input.Substring(input.LastIndexOf('\n'))` would be enough here. – Adi Lester Feb 11 '12 at 11:52
  • 1
    In your answer the perfomance is thw worst, you need to read all string to string, there is no need for this. – Dor Cohen Feb 11 '12 at 11:59
  • 3
    @DorCohen You are a better mindreader than I. Based on the question and the given example I didn't dreamed up that the OP was reading a file. But given the fact that your answer got accepted I guess I have to work on my subliminal capabilities :) – rene Feb 11 '12 at 12:14
  • 1
    @DorCohen It does not state anywhere in the question that string is read from a file. I would consider this the correct answer +1 – Magnus Feb 11 '12 at 12:15
  • I mean string, but I tried to save string as file and then read it, I am not sure, if yours or DorCohen solution is better – Martin Ch Feb 11 '12 at 12:38
  • 1
    What if the file ends with a new line? – Marco Sulla Jun 21 '16 at 10:02
3

If you create a new IO.FileStream() object, there's a .Seek() method that will allow you specify the end of the file as part of where you want to seek to. However, at this point there's no straightforward way to see where the last line starts. You'll have to either walk backwards looking for a line, or if you have an idea of what this last line looks like (and therefore how long it is) you might be able to make a guess as to how far back you need to seek and go just a little further. Use the FileStream.CanSeek property to determine whether the current instance supports seeking. For additional information, see Stream.CanSeek.

FileStream  fileStream = new FileStream(fileName, FileMode.Open)
// Set the stream position to the end of the file.
fileStream.Seek(0, SeekOrigin.End);

then go over in loop until you get your /n

you can also read in this other question: How to read a text file reversely with iterator in C#

Community
  • 1
  • 1
Dor Cohen
  • 16,769
  • 23
  • 93
  • 161
  • I edited my answer, Pay attention that in my answer the perfomance is optimized, there is no need to read entire file! – Dor Cohen Feb 11 '12 at 12:00
1

If you need better performance when reading any file, You can go for memory map file reading/writing, that is to work at the low level APIs.

user1058272
  • 113
  • 2
  • 9
0

(Note: It's not C# but VB.NET) I translated a function that I created for Python a few time ago. Not sure that searching for \n only is the best choice...

Public Function tail(ByVal filepath As String) As String
    ' @author marco sulla (marcosullaroma@gmail.com)
    ' @date may 31, 2016

    Dim fp As String = filepath
    Dim res As String

    Using f As FileStream = File.Open(fp, FileMode.Open, FileAccess.Read)
        Dim f_info As New FileInfo(fp)
        Dim size As Long = f_info.Length
        Dim start_pos As Long = size - 1

        If start_pos < 0 Then
            start_pos = 0
        End If

        If start_pos <> 0 Then
            f.Seek(start_pos, SeekOrigin.Begin)
            Dim mychar As Integer = f.ReadByte()

            If mychar = 10 Then  ' newline
                start_pos -= 1
                f.Seek(start_pos, SeekOrigin.Begin)
            End If

            If start_pos = 0 Then
                f.Seek(start_pos, SeekOrigin.Begin)
            Else
                mychar = -1

                For pos As Long = start_pos To 0 Step -1
                    f.Seek(pos, SeekOrigin.Begin)

                    mychar = f.ReadByte()

                    If mychar = 10 Then
                        Exit For
                    End If
                Next
            End If
        End If

        Using r As StreamReader = New StreamReader(f, Encoding.UTF8)
            res = r.ReadLine()
        End Using
    End Using

    Return res
End Function
Community
  • 1
  • 1
Marco Sulla
  • 15,299
  • 14
  • 65
  • 100