By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,435 Members | 1,448 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,435 IT Pros & Developers. It's quick & easy.

Read line after line but from the eof.

P: n/a
Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)

I want to copy file in this way:

file 1:

a
b
c
file 2:

c
b
a
--
Ground21____________\\
ground21@pocztaKROPKAfm
Dec 22 '06 #1
Share this Question
Share on Google+
24 Replies


P: n/a
Ground21 wrote:
Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)

I want to copy file in this way:

file 1:

a
b
c
file 2:

c
b
a
The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should work
ok.

Dec 22 '06 #2

P: n/a
The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should work
ok.
I think I wrote bad example:

Once more:

file1:

text1
text2
text3
abctest

file2:

abctest
text3
text2
text1
--
Ground21____________\\
ground21@pocztaKROPKAfm
Dec 22 '06 #3

P: n/a
Ground21 wrote:
>
>The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should
work ok.

I think I wrote bad example:
I did understand your posting anyway.
Once more:

file1:

text1
text2
text3
abctest

file2:

abctest
text3
text2
text1
Yup. What you should do is read the file line by line and put each line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.

Dec 22 '06 #4

P: n/a

Rolf Magnus napsal:
Ground21 wrote:
The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should
work ok.
I think I wrote bad example:

I did understand your posting anyway.
Once more:

file1:

text1
text2
text3
abctest

file2:

abctest
text3
text2
text1

Yup. What you should do is read the file line by line and put each line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.
I would recommend std::list instead of std::vector, because list can be
simplier (== more effectively) extended in length.

Dec 22 '06 #5

P: n/a
Ondra Holub wrote:
Rolf Magnus napsal:
>Ground21 wrote:
>>>The easiest way would be to read all the lines into something like an
std::vector<std::string, then write the new file iterating backwards
through the vector. As long as you don't have huge files, this should
work ok.
I think I wrote bad example:
I did understand your posting anyway.
>>Once more:

file1:

text1
text2
text3
abctest

file2:

abctest
text3
text2
text1
Yup. What you should do is read the file line by line and put each line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.

I would recommend std::list instead of std::vector, because list can be
simplier (== more effectively) extended in length.
I used deque.

I tried to be real clever, with reverse_copy on an istream_iterator, and
an ostream_iterator, but reverse_copy requires Bidirectional Iterators. :(
Dec 22 '06 #6

P: n/a
Rolf Magnus napisał(a):
Yup. What you should do is read the file line by line and put each line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.
can You tell me what's wrong with this code?:
(I want to save lines from file 'file' to vectors, and then, write them
into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem
with char*...

#include <vector.h>
vector <char*tab(10);

tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++)
{
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--)
{
fputs(tab[i],tmp);
}
--
Ground21____________\\
ground21@pocztaKROPKAfm
Dec 22 '06 #7

P: n/a
Ground21 wrote:
Rolf Magnus napisał(a):
>Yup. What you should do is read the file line by line and put each
line as a
separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.

can You tell me what's wrong with this code?:
(I want to save lines from file 'file' to vectors, and then, write them
into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem
with char*...

#include <vector.h>
vector <char*tab(10);

tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++)
{
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--)
{
fputs(tab[i],tmp);
}

Lets see...

1. What is "lines"?
2. What happens if there are more than 10 lines in a file?
3. What happens if a line is bigger than 256?
4. Why are you using arrays and C-style I/O?
5. What is <vector.h>? The C++ header is <vector>
6. Every entry in your vector is identical, since you're storing the
same address over and over.

And that's just off the top of my head.

Dec 22 '06 #8

P: n/a
red floyd napisał(a):
1. What is "lines"?
int lines=0;
fseek(fileh,0L,SEEK_SET);
while(feof(fileh)==0) if(fgetc(fileh)=='\n') linies++;

lines - number of lines in my text file.
2. What happens if there are more than 10 lines in a file?
I read in wikibooks, that value of size will automaticlly increase if
necessary...

3. What happens if a line is bigger than 256?
I know, that it can be done better using something like strlen to check
line lenght, but for me, 256 is OK.
4. Why are you using arrays and C-style I/O?
5. What is <vector.h>? The C++ header is <vector>
in c++ builder 6 it works the same for <vectorand <vector.h>...
6. Every entry in your vector is identical, since you're storing the
same address over and over.

I though, that I take first line to tab[0], second line to tab[1]...

--
Ground21____________\\
ground21@pocztaKROPKAfm
Dec 22 '06 #9

P: n/a
r
Ground21 wrote:
>
can You tell me what's wrong with this code?:
(I want to save lines from file 'file' to vectors, and then, write them
into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem
with char*...

#include <vector.h>
vector <char*tab(10);

tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++)
{
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--)
{
fputs(tab[i],tmp);
}
It's a bad mix of C and C++, besides the "Access violation".

// reading a file line by line
std::ifstream ifs ("tmp.txt");
std::string line;
std::vector<std::stringlines;
while (getline (ifs, line)) {
lines.push_back(line);
}

Is this already in the C++ FAQ?

Dec 22 '06 #10

P: n/a
Ground21 wrote:
red floyd napisał(a):
>1. What is "lines"?
int lines=0;
fseek(fileh,0L,SEEK_SET);
while(feof(fileh)==0) if(fgetc(fileh)=='\n') linies++;

lines - number of lines in my text file.
>2. What happens if there are more than 10 lines in a file?

I read in wikibooks, that value of size will automaticlly increase if
necessary...
Yes, if you use the push_back member function.
>3. What happens if a line is bigger than 256?

I know, that it can be done better using something like strlen to check
line lenght, but for me, 256 is OK.
It would be better as well as easier to use std::string instead of raw char
arrays and pointers.
>4. Why are you using arrays and C-style I/O?
5. What is <vector.h>? The C++ header is <vector>

in c++ builder 6 it works the same for <vectorand <vector.h>...
Well, then you better stick to the standard header <vector>, otherwise your
program will be non-portable.
>6. Every entry in your vector is identical, since you're storing the
same address over and over.


I though, that I take first line to tab[0], second line to tab[1]...
You could try something based on this (untested):

#include <istream>
#include <ostream>
#include <string>
#include <vector>

void reverse_copy_file(std::istream& infile, std::ostream& outfile)
{
typedef std::vector<std::string vec_type;
vec_type text;

std::string line;
while (std::getline(infile, line))
text.push_back(line);

vec_type::const_reverse_iterator it = text.rbegin(), end = text.rend();
for (; it != end; ++it)
outfile << line << '\n';
}
Dec 22 '06 #11

P: n/a
r wrote:
// reading a file line by line
std::ifstream ifs ("tmp.txt");
std::string line;
std::vector<std::stringlines;
while (getline (ifs, line)) {
lines.push_back(line);
}

Is this already in the C++ FAQ?
[C++ Error] zapis.cpp(136): E2285 Could not find a match for
'getline<_CharT,_Traits,_Alloc>(FILE *,string)'

--
Ground21____________\\
ground21@pocztaKROPKAfm
Dec 22 '06 #12

P: n/a
Ground21 wrote:
r wrote:
>// reading a file line by line
std::ifstream ifs ("tmp.txt");
std::string line;
std::vector<std::stringlines;
while (getline (ifs, line)) {
lines.push_back(line);
}

Is this already in the C++ FAQ?

[C++ Error] zapis.cpp(136): E2285 Could not find a match for
'getline<_CharT,_Traits,_Alloc>(FILE *,string)'
That's because you didn't copy the whole example. He used an ifstream
for input, not a FILE*.

Use C++ style I/O if you're writing C++.
Dec 23 '06 #13

P: n/a

Ground21 wrote in message ...
>Rolf Magnus napisał(a):
>Yup. What you should do is read the file line by line and put each line as
a
>separate string into a vector. So later you have a vector of lines. Then
you can iterate through that vector backwards and write the strings out
again.

can You tell me what's wrong with this code?:
(I want to save lines from file 'file' to vectors, and then, write them
into "tmp.txt"). I got wrong output "tmp.log"... I think that is problem
with char*...
// >#include <vector.h>
#include <vector// C++
>vector <char*tab(10);
tmp=fopen("tmp.txt","w");
fseek(file, 0L, SEEK_SET);
for(int i=0; i<lines; i++){
fgets(tab[i],256,file);
}
for(int i=lines; i>0; i--){
fputs(tab[i],tmp);
}

#include <vector// C++
#include <string>
#include <fstream>
#include <algorithm>

int main(){
std::ifstream copin( "ZZtest.txt" );
if( not copin.is_open() ){ throw "a fit";}

std::vector<std::stringTmpFile;
for( std::string line; std::getline( copin, line ); ){
TmpFile.push_back(line);
}
// copin.close();
std::reverse( TmpFile.begin(), TmpFile.end() ); // reverse it
std::ofstream out( "ZZtestR.txt" );
for( size_t i(0); i < TmpFile.size(); ++i ){
std::reverse( TmpFile.at(i).begin(), TmpFile.at(i).end());
out<< TmpFile.at( i ) <<std::endl;
}
// out.close();
} // main()
// ----------
// - contents "ZZtest.txt" -
Record 0
Record 1
Record 2
Record 3
Record 4
Record 5
Record 6

// - contents "ZZtestR.txt" -
6 droceR
5 droceR
4 droceR
3 droceR
2 droceR
1 droceR
0 droceR

--
Bob R
POVrookie
Dec 23 '06 #14

P: n/a
Ground21 wrote:
Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)

I want to copy file in this way:

file 1:

a
b
c
file 2:

c
b
a

I think the most simple solution would use a stack an C++ I/O.

#include <iostream>
#include <fstream>
#include <stack>
#include <string>

using namespace std;

int main()
{
ifstream in("in.txt");
ofstream out("out.txt");
stack<stringss;

string s;
in >s;
while (!in.eof()) {
ss.push(s);
in >s;
}
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop();
}
return 0;
}

Dec 23 '06 #15

P: n/a
Tobias Gneist wrote:
Ground21 wrote:
>Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)

I want to copy file in this way:

file 1:

a
b
c
file 2:

c
b
a


I think the most simple solution would use a stack an C++ I/O.
Hmm, right. A stack is actually a better choice than a vector.
#include <iostream>
#include <fstream>
#include <stack>
#include <string>

using namespace std;

int main()
{
ifstream in("in.txt");
ofstream out("out.txt");
stack<stringss;

string s;
in >s;
while (!in.eof()) {
ss.push(s);
in >s;
}
Simpler and more correct than those last 5 lines would be:

while (in >s)
ss.push(s);
while (!ss.empty()) {
out << ss.top() << endl;
No need to flush the stream after each line, so '\n' instead of endl is
sufficient.
ss.pop();
}
return 0;
}
Dec 23 '06 #16

P: n/a
I think the most simple solution would use a stack an C++ I/O.
>
#include <iostream>
#include <fstream>
#include <stack>
#include <string>

using namespace std;

int main()
{
ifstream in("in.txt");
ofstream out("out.txt");
stack<stringss;

string s;
in >s;
while (!in.eof()) {
ss.push(s);
in >s;
}
If input likes:

test
122 345 345

output would be:

345
345
122
test

How about this

while (std::getline(in,s)) {
ss.push(s);
}

output would be:

122 345 345
test
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop();
}
return 0;
}
Dec 23 '06 #17

P: n/a
gongzibi napisał(a):
How about this

while (std::getline(in,s)) {
ss.push(s);
}

output would be:

122 345 345
test
ifstream in("log.txt");
ofstream out("out.txt");
stack<stringss;

string s;
in >s;

while (std::getline(in,s)) {
ss.push(s);
}
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop(); }

this code works OK, but...

my log.txt file:

d/t: 2006-12-23/18:52:47 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe

and output file:

d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe
2006-12-23/18:52:47 D:\c++\sem1\Project1.exe

where is my "d/t: " ?
--
Ground21____________\\
ground21@pocztaKROPKAfm
Dec 23 '06 #18

P: n/a

Ground21 wrote in message ...
>
ifstream in("log.txt");
ofstream out("out.txt");
stack<stringss;

string s;
in >s;

while (std::getline(in,s)) {
ss.push(s);
}
while (!ss.empty()) {
out << ss.top() << endl;
ss.pop(); }

this code works OK, but...

my log.txt file:

d/t: 2006-12-23/18:52:47 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe

and output file:

d/t: 2006-12-23/18:52:52 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:50 D:\c++\sem1\Project1.exe
d/t: 2006-12-23/18:52:49 D:\c++\sem1\Project1.exe
2006-12-23/18:52:47 D:\c++\sem1\Project1.exe

where is my "d/t: " ?
string s;
in >s; // it's in this string you didn't save.
// delete that line.

while (std::getline(in,s)) { ss.push(s); }

--
Bob R
POVrookie
Dec 23 '06 #19

P: n/a
BobR napisał(a):
>where is my "d/t: " ?

string s;
in >s; // it's in this string you didn't save.
// delete that line.

while (std::getline(in,s)) { ss.push(s); }
works great!
thanks a lot!

--
Ground21____________\\
ground21@pocztaKROPKAfm
Dec 23 '06 #20

P: n/a
Ground21 ():
Hello.
How could I read the whole text file line after line from the end of
file? (I want to ~copy~ file)
Take it, i am slightly adapted it for C++ from C:
Declare in your program:

#include <stdio.h>

namespace NGround21
{
typedef unsigned int uint;

// store 'max_visible_chars' chars maximum to 'buf' and close by \0
//( ! ADD '\0' char to buf, total size can be 'max_visible_chars' +1
maximum )
// all 256 chars of DOS/Win/UNIX <EOLallowed
//special: to skip all chars till <EOLwrite:
getln(any_number,0,correct_pointer);

// "fi" must be open as "rb"
// return 0 if errors in parameters, else return !0
// "fi" file pointer will be after <EOLif return !0
char getln(char *const buf, const uint max_visible_chars, FILE
*const fi)throw();

//namespace NGround21
}
using namespace NGround21;

Write as separated cpp file, compile it and then link object file to
your project

#include <stdio.h>

char NGround21::getln(
char *const buf,
const uint max_visible_chars,
FILE *const fp
)throw()
{
if(
( (max_visible_chars) && (!buf) )
||( !fp )
)return 0;

char *p=buf;
for( uint len=0; ; )
{
int ch=fgetc(fp);
if( feof(fp) )break;

if( ch==13 )continue;
if( ch==10 )break;

if( len >= max_visible_chars )continue;

++len;
*p++=static_cast<char>(ch);
}

if( p ) *p=0;
return 1;
}

Jan 14 '07 #21

P: n/a

Oy, google makes error, look to the sorted list:

Building Compatible Libraries 11 11 Peter Olcott
(: 4) 11 .
Simple program 20 Ground21 (: 4) 18 . 2006
Read line after line but from the eof. 27 Ground21 (:
8) 24 . 2006
Something Strange From the Days Way Before C++ 9 9
Tim Slattery (: 7) 11 .
Possible causes for the 'delete ptr;' to core?? 7
7 Noah Roberts (: 6) 11 .

Jan 14 '07 #22

P: n/a
I have the same need, but it needs to be done for a large file (~
5GB).
So I don't want to use stack/vector/queus etc.,

any efficient C++ / STL solution would be great

Thanks,
SK

On Jan 14, 3:17 pm, "Grizlyk" <grizl...@yandex.ruwrote:
Ground21 ():
Hello.
How could Ireadthe whole textfileline after line from the end of
file? (I want to ~copy~file)

Take it, i am slightly adapted it for C++ from C:
Declare in your program:

#include <stdio.h>

namespace NGround21
{
typedef unsigned int uint;

// store 'max_visible_chars' chars maximum to 'buf' and close by \0
//( ! ADD '\0' char to buf, total size can be 'max_visible_chars' +1
maximum )
// all 256 chars of DOS/Win/UNIX <EOLallowed
//special: to skip all chars till <EOLwrite:
getln(any_number,0,correct_pointer);

// "fi" must be open as "rb"
// return 0 if errors in parameters, else return !0
// "fi"filepointer will be after <EOLif return !0
char getln(char *const buf, const uint max_visible_chars,FILE
*const fi)throw();

//namespace NGround21}

using namespace NGround21;

Write as separated cppfile, compile it and then link objectfileto
your project

#include <stdio.h>

char NGround21::getln(
char *const buf,
const uint max_visible_chars,
FILE*const fp
)throw()
{
if(
( (max_visible_chars) && (!buf) )
||( !fp )
)return 0;

char *p=buf;
for( uint len=0; ; )
{
int ch=fgetc(fp);
if( feof(fp) )break;

if( ch==13 )continue;
if( ch==10 )break;

if( len >= max_visible_chars )continue;

++len;
*p++=static_cast<char>(ch);
}

if( p ) *p=0;
return 1;

}- Hide quoted text -

- Show quoted text -

Feb 26 '07 #23

P: n/a
On 26 Feb, 14:52, "SKumar" <SureshKumar...@gmail.comwrote:
I have the same need, but it needs to be done for a large file (~
5GB).
So I don't want to use stack/vector/queus etc.,

any efficient C++ / STL solution would be great
If its too big for memory. Read as many as you can to the stack.
when attempting to push stack throws bad_alloc pop all the stack to a
unique name temp file. (You need to take care to not lose the last bit
of input data of course, but the stack contents that succeeded should
not be violated)
save the unique temp filenames on another stack.
then start again reading data, starting with the last bit of data that
failed.
when the input is done pop the filename stack one by one and read the
resulting files to your output file.

To speed things up you could preallocate a big chunk in your stack
container. You would probably need to experiment to find how much
memory you can grab, just keep catching exceptions and reducing the
size.

Untested .... ;-)

regards
Andy Little




Feb 26 '07 #24

P: n/a
On 26 Feb, 17:31, "kwikius" <a...@servocomm.freeserve.co.ukwrote:
On 26 Feb, 14:52, "SKumar" <SureshKumar...@gmail.comwrote:
I have the same need, but it needs to be done for a large file (~
5GB).
So I don't want to use stack/vector/queus etc.,
any efficient C++ / STL solution would be great

If its too big for memory. Read as many as you can to the stack.
when attempting to push stack throws bad_alloc pop all the stack to a
unique name temp file. (You need to take care to not lose the last bit
of input data of course, but the stack contents that succeeded should
not be violated)
save the unique temp filenames on another stack.
then start again reading data, starting with the last bit of data that
failed.
when the input is done pop the filename stack one by one and read the
resulting files to your output file.

To speed things up you could preallocate a big chunk in your stack
container. You would probably need to experiment to find how much
memory you can grab, just keep catching exceptions and reducing the
size.

Untested .... ;-)

regards
Andy Little

There is a fatal flaw in this scheme, which is that when you try to
push your filename stack you will probably get bad_alloc too. Youre
all out of memory :-)
You will need to find a way to give the system some memory back when
required, or try a less agressive approach to the whole thing ;-)

regards
Andy Little

Feb 26 '07 #25

This discussion thread is closed

Replies have been disabled for this discussion.