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:
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
load your file by chunks from end into memory
so make a static buffer and load file into it from end by chunks ...
stop on
eol
(end of line) usuallyCR,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
eol
s are:13
10
13,10
10,13construct 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:
- Go to the end of the file
- Read last X bytes
- If they contain '\n' - you got your line - read from that offset to the end of the file
- Read X bytes before them
- back to 3 until match found
- 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
What Is the Idiomatic Way in Cmake to Add the -Fpic Compiler Option
Automatic Perspective Correction Opencv
C++ Getters/Setters Coding Style
Vector or Map, Which One to Use
Dead Code Detection in Legacy C/C++ Project
Are There Any Better Methods to Do Permutation of String
How Does the Custom Deleter of Std::Unique_Ptr Work
How to Generate the Audio Spectrum Using Fft in C++
Can You Make Custom Operators in C++
How to Get the Number of Characters in a Std::String
Is There a Good Python Library That Can Parse C++
C++ For-Loop - Size_Type VS. Size_T
Accessing Environment Variables in C++
Cout or Printf Which of the Two Has a Faster Execution Speed C++
Conversion from String Literal to Char* Is Deprecated
Linux Equivalent for Conio.H Getch()