PDA

View Full Version : Reading a text file from end



anh5kor
11th March 2015, 08:24
Hello,

Please let me how can I read a text file from last line to first line.
or is there any function in Qt which can I use in my code.

ChrisW67
11th March 2015, 08:48
How big is the file? 10 lines, 10000 lines, or 10 billion lines?

anh5kor
11th March 2015, 11:03
It's a dynamic size File it can be 10 lines,10000lines or 10 billion lines also
Size is not fixed.

Lesiok
11th March 2015, 11:55
Generally a file is an "unidirectional device" i.e. it can read/write data only in one direction from begin to end.

anh5kor
11th March 2015, 11:57
There is no way that I can read file from end to begin because this
the requirement for my Project.

Lesiok
11th March 2015, 12:05
Say some more about this file. Is the structure of the file somehow ordered? Lines have a fixed length or variable?

anh5kor
11th March 2015, 12:26
ok
Actually in my GUI I have two button connect and disconnect on connect it will start writing to file and on disconnect it will stop.
I have the Structure also
Below is the code for Write File


void ui_logging::log_report()
{
QTextStream stream(file);
int index = 0;

stream << "ECU->USS\n";
stream <<"Sensor"<<" "<<"Time"<<" "<<"Data"<<endl;
for(int i = 0;i<12;i++)
{
stream << "USS"<<i+1<<" ";

stream<<time_log_ecu2uss[i];
if(i<9)
{
stream<<" ";
}
else
{
stream<<" ";
}

for(int j = 0;j<4;j++)
{

stream<<("0x"+QString::number(Data_ecu2uss[index],16));
if(j<3)
{
stream<<" ";
}
index++;
}

stream<<endl;
}

index = 0 ;
stream << "USS->ECU\n";
stream <<"Sensor"<<" "<<"Time"<<" "<<"Data"<<endl;
for(int i = 0;i<12;i++)
{
stream << "USS"<<i+1<<" ";
stream<<time_log_uss2ecu[i];
if(i<9)
{
stream<<" ";
}
else
{
stream<<" ";
}
for(int j = 0;j<4;j++)
{
stream<<("0x"+QString::number(Data_uss2ecu[index],16));
if(j<3)
{
stream<<" ";
}
index++;
}
stream<<endl;
}

stream<<"************************************************** ****************"<<endl;

}

Where my file Look like below
ECU->USS
Sensor Time Data
USS1 12:25:15 0x0 0x0 0x0 0x0
USS2 12:25:15 0x0 0x0 0x0 0x0
USS3 12:25:15 0x0 0x0 0x0 0x0
USS4 12:25:15 0x0 0x0 0x0 0x0
USS5 12:25:15 0x0 0x0 0x0 0x0
USS6 12:25:15 0x0 0x0 0x0 0x0
USS7 12:25:15 0x0 0x0 0x0 0x0
USS8 12:25:15 0x0 0x0 0x0 0x0
USS9 12:25:15 0x0 0x0 0x0 0x0
USS10 12:25:15 0x0 0x0 0x0 0x0
USS11 12:25:15 0x0 0x0 0x0 0x0
USS12 12:25:15 0x0 0x0 0x0 0x0
USS->ECU
Sensor Time Data
USS1 12:25:15 0x0 0x0 0x0 0x0
USS2 12:25:15 0x0 0x0 0x0 0x0
USS3 12:25:15 0x0 0x0 0x0 0x0
USS4 12:25:15 0x0 0x0 0x0 0x0
USS5 12:25:15 0x0 0x0 0x0 0x0
USS6 12:25:15 0x0 0x0 0x0 0x0
USS7 12:25:15 0x0 0x0 0x0 0x0
USS8 12:25:15 0x0 0x0 0x0 0x0
USS9 12:25:15 0x0 0x0 0x0 0x0
USS10 12:25:15 0x0 0x0 0x0 0x0
USS11 12:25:15 0x0 0x0 0x0 0x0
USS12 12:25:15 0x0 0x0 0x0 0x0
************************************************** ****************
ECU->USS
Sensor Time Data
USS1 12:25:16 0x0 0x0 0x0 0x0
USS2 12:25:16 0x0 0x0 0x0 0x0
USS3 12:25:16 0x0 0x0 0x0 0x0
USS4 12:25:16 0x0 0x0 0x0 0x0
USS5 12:25:16 0x0 0x0 0x0 0x0
USS6 12:25:16 0x0 0x0 0x0 0x0
USS7 12:25:16 0x0 0x0 0x0 0x0
USS8 12:25:16 0x0 0x0 0x0 0x0
USS9 12:25:16 0x0 0x0 0x0 0x0
USS10 12:25:16 0x0 0x0 0x0 0x0
USS11 12:25:16 0x0 0x0 0x0 0x0
USS12 12:25:16 0x0 0x0 0x0 0x0
USS->ECU
Sensor Time Data
USS1 12:25:16 0x0 0x0 0x0 0x0
USS2 12:25:16 0x0 0x0 0x0 0x0
USS3 12:25:16 0x0 0x0 0x0 0x0
USS4 12:25:16 0x0 0x0 0x0 0x0
USS5 12:25:16 0x0 0x0 0x0 0x0
USS6 12:25:16 0x0 0x0 0x0 0x0
USS7 12:25:16 0x0 0x0 0x0 0x0
USS8 12:25:16 0x0 0x0 0x0 0x0
USS9 12:25:16 0x0 0x0 0x0 0x0
USS10 12:25:16 0x0 0x0 0x0 0x0
USS11 12:25:16 0x0 0x0 0x0 0x0
USS12 12:25:16 0x0 0x0 0x0 0x0
************************************************** ****************
It will write until and unless I stop the button
Now I have two button called Read_up2down which will read the data from USS1 to USS12 on every click and Read_down2up which will read the data from USS12 to USS1 and rest element has to be ignored.
I am able to read data from USS1 to USS12 but not from USS12 to USS1
Below is the code for Read_up2down


void ui_logging::Read_up2down()
{
count++;

QTextStream in(file);
//get position of file
if(!flag_Position)
{
in.seek(n);
}

for( i = 0;i<4;i++)//Ignore the unused data
{

in>>str1;
qDebug()<<str1;
}
for(int i = 0;i<72;i++)//Get the used data first time
{
in>>str[i];
qDebug()<<str[i];

}
if(count == 2)//ignore the *** every time
{
in>>str1;
qDebug()<<str1;
count = 0;
}

n = in.pos();
in.skipWhiteSpace();
flag_Position = false;

}

O/p:
1st Click
"ECU->USS"
"Sensor"
"Time"
"Data"
"USS1"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS2"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS3"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS4"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS5"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS6"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS7"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS8"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS9"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS10"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS11"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS12"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
2nd Click
"USS->ECU"
"Sensor"
"Time"
"Data"
"USS1"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS2"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS3"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS4"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS5"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS6"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS7"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS8"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS9"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS10"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS11"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"USS12"
"12:25:15"
"0x0"
"0x0"
"0x0"
"0x0"
"************************************************** ****************"
and so on...

Lesiok
11th March 2015, 12:35
Maybe using some SQL database (e.g. SQLite) is a solution ?

wysota
11th March 2015, 15:38
To read a file from the end seek to the end of file, seek back a defined number of bytes (e.g. 4kB to match the memory page size), read those 4kB into a buffer, scan the buffer character by character starting from the end for a newline. When found, this marks the end of your previous-to-last line and the last line is everything past it. Process and repeat. If there is no newline, read another chunk from from the file and carry on.

ChrisW67
11th March 2015, 20:28
Anh5kor, it turns outs, does not actually want to read the file backward line by line. Rather, the desire is to read multiline blocks in reverse order from the file, but read the content of each block in a forward direction.

An adaptation of wysota's approach that looks backward for "ECU->USS\n" rather than a lone newline should provide the place to start reading a block from.

With potentially billions of lines/blocks then a fixed block size (binary or text), a separately written index file of block start offsets, or storage in a database, would also be options.