C++ Fastest Way to Read Only Last Line of Text File

c++ fastest way to read only last line of text file?

Use seekg to jump to the end of the file, then read back until you find the first newline.
Below is some sample code off the top of my head using MSVC.

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

int main()
{
string filename = "test.txt";
ifstream fin;
fin.open(filename);
if(fin.is_open()) {
fin.seekg(-1,ios_base::end); // go to one spot before the EOF

bool keepLooping = true;
while(keepLooping) {
char ch;
fin.get(ch); // Get current byte's data

if((int)fin.tellg() <= 1) { // If the data was at or before the 0th byte
fin.seekg(0); // The first line is the last line
keepLooping = false; // So stop there
}
else if(ch == '\n') { // If the data was a newline
keepLooping = false; // Stop at the current position.
}
else { // If the data was neither a newline nor at the 0 byte
fin.seekg(-2,ios_base::cur); // Move to the front of that data, then to the front of the data before it
}
}

string lastLine;
getline(fin,lastLine); // Read the current line
cout << "Result: " << lastLine << '\n'; // Display it

fin.close();
}

return 0;
}

And below is a test file. It succeeds with empty, one-line, and multi-line data in the text file.

This is the first line.
Some stuff.
Some stuff.
Some stuff.
This is the last line.

only read last line of text file (C++ Builder)

Exactly as Remy Lebeau commented:

  1. Use file access functions FileOpen,FileSeek,FileRead

    look here for example of usage:

    • Convert the Linux open, read, write, close functions to work on Windows
  2. load your file by chunks from end into memory

    so make a static buffer and load file into it from end by chunks ...

  3. stop on eol (end of line) usually CR,LF

    just scan for 13,10 ASCII codes or their combinations from end of chunk. Beware some files have last line also terminated so you should skip that the first time ...

    known eols are:

    13
    10
    13,10
    10,13
  4. construct line

    if no eol found add whole chunk to string, if found add just the part after it ...

Here small example:

int hnd,siz,i,n;
const int bufsz=256; // buffer size
char buf[bufsz+1];
AnsiString lin; // last line output
buf[bufsz]=0; // string terminator
hnd=FileOpen("in.txt",fmOpenRead); // open file
siz=FileSeek(hnd,0,2); // obtain size and point to its end
for (i=-1,lin="";siz;)
{
n=bufsz; // n = chunk size to load
if (n>siz) n=siz; siz-=n;
FileSeek(hnd,siz,0); // point to its location (from start)
FileRead(hnd,buf,n); // load it to buf[]
if (i<0) // first time pass (skip last eol)
{
i=n-1; if (i>0) if ((buf[i]==10)||(buf[i]==13)) n--;
i--; if (i>0) if ((buf[i]==10)||(buf[i]==13)) if (buf[i]!=buf[i+1]) n--;
}
for (i=n-1;i>=0;i--) // scan for eol (CR,LF)
if ((buf[i]==10)||(buf[i]==13))
{ siz=0; break; } i++; // i points to start of line and siz is zero so no chunks are readed after...
lin=AnsiString(buf+i)+lin; // add new chunk to line
}
FileClose(hnd); // close file
// here lin is your last line

Read last line of a text file - C programming

In your fscanf(tfptr, "%u:%u:%.2f\n", &combo_trans, &ala_trans, &grand_total);, the %.2f will cause problem.

You can't specify the precision for floating-point numbers in scanf() unlike in the case of printf(). See this answer.

So, instead of %.2f in the scanf format string, use just %f.

Since you just need the last line, you could just read the file line by line with fgets() and keep the last line.

while( fgets(str, sizeof(str), tfptr)!=NULL );
printf("\nLast line: %s", str);

fgets() will return NULL when the file is over (or if some error occurred while reading).

The lines in the input file are read one by one and when there are no more lines to read, str (a character array of suitable size) will have the line that was read last.

You could then parse the string in str with sscanf() like

sscanf(str, "%u:%u:%f", &combo_trans, &ala_trans, &grand_total);

Also, you should be checking the return value of fopen() to see if the file was really opened. fopen() will return NULL if some error occurred.

if( (tfptr = fopen("trans.txt", "r"))==NULL )
{
perrror("Error");
}

How can i select the last line of a text file using C

No direct way, but my preferred method is:

  1. Go to the end of the file
  2. Read last X bytes
  3. If they contain '\n' - you got your line - read from that offset to the end of the file
  4. Read X bytes before them
  5. back to 3 until match found
  6. If reached the beginning of the file - the whole file is the last line

How to efficiently read only last line of the text file

You want to read the file backwards using ReverseLineReader:

How to read a text file reversely with iterator in C#

Then run .Take(1) on it.

var lines = new ReverseLineReader(filename);
var last = lines.Take(1);

You'll want to use Jon Skeet's library MiscUtil directly rather than copying/pasting the code.

C: read only last line of a file. No loops

If there is a maximum line length, seek to that distance before the end.
Read up to the end, and find the last end-of-line in your buffer.

If there is no maximum line length, guess a reasonable value, read that much at the end, and if there is no end-of-line, double your guess and try again.

In your case:

/* max length including newline */
static const long max_len = 55 + 1;
/* space for all of that plus a nul terminator */
char buf[max_len + 1];

/* now read that many bytes from the end of the file */
fseek(fd, -max_len, SEEK_END);
ssize_t len = read(fd, buf, max_len);

/* don't forget the nul terminator */
buf[len] = '\0';

/* and find the last newline character (there must be one, right?) */
char *last_newline = strrchr(buf, '\n');
char *last_line = last_newline+1;

How do I read the last line of a text file in a C program?

Compare these two programs, one (mis)using feof() and one not using it at all. The first corresponds closely to the code in the question — it ignores the return value from fgets() to its detriment. The second only tests the return value from fgets(); it has no need to use feof().

eof53.c

#include <stdio.H>

int main(void)
{
char buffer[256];

fgets(buffer, sizeof(buffer), stdin);
while (!feof(stdin))
{
printf("[%s]\n", buffer);
fgets(buffer, sizeof(buffer), stdin);
}
return 0;
}

eof71.c

#include <stdio.H>

int main(void)
{
char buffer[256];

while (fgets(buffer, sizeof(buffer), stdin) != NULL)
printf("[%s]\n", buffer);
return 0;
}

Given a data file abc containing 3 bytes — 0x41 ('A'), 0x42 ('B'), 0x43 ('C') and no newline, I get the following results:

$ eof53 < abc
$ eof71 < abc
[ABC]
$

This was tested on MacOS Big Sur 11.6.6.

Note that fgets() does not report EOF (by returning a null pointer) when reading the (only) incomplete line, but empirically, feof() does report EOF — correctly, since the file input has ended, even though fgets() did return a string (but not a line) of data.

As explained in the canonical Q&A while (!feof(file)) is always wrong!, using feof() rather than testing the return value from the I/O functions leads to bad results.

C++ getline() is only reading the last line in a text file

You have a semicolon after the while loop which means it will keep iterating and do nothing as you have an empty statement (; means empty statement). This is why you got the last line as line was filled with the last line of your file in the last(3rd) iteration.

while (std::getline(ReadFile, line));

Update your while loop as shown below to get the desired result:

while (std::getline(ReadFile, line))
{
std::cout << line << "\n";
}


Related Topics



Leave a reply



Submit