Help! Can't read backwards from end of file

Not sure what I'm doing wrong. I can't get the data to display on the console for menu option #2. I'm only getting the cout statement for "Reading contents backwards...." , but nothing else. Option #1 works ok. ANY IDEAS?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
#include <string>
#include <iomanip>
#include <istream>
#include <math.h>
#include <fstream>

using namespace std;

const int SIZE = 20;                     
typedef char String[SIZE];

//prototypes
void Menu(int &);
void ReadFile(ifstream &);
void BackwardFile(ifstream &);
int CountFile(ifstream &,int &);


int main()
 {  
    char filename[]= "grades.txt";
    int choice, numBytes;
    
    ifstream InList;
    InList.open(filename);
    
    if(InList.good())
    {
         do
         {         
         Menu(choice); 
         switch(choice)
        	{
            case 1:  
                   ReadFile(InList);
                   break;
            case 2:
                   BackwardFile(InList);
                   break;
            case 3:
                   CountFile(InList,numBytes);
                   cout << "Pick a start position between 0 - " << numBytes << endl;
                   break;
            /*case 4:*/
            
            case 5:
                   cout << "\n GOOD BYE." << endl << endl; 
                   break;
            }
         
         }while (choice != 5);                         
    }
	else
         cout << "File did not open successfully." << endl << endl;
          
          
    system("PAUSE");
    return EXIT_SUCCESS;

}
 

    void Menu(int &choice) 
    { 
         cout << "\n    Choose an option:";
	     cout << "\n...................................";
         cout << "\n 1- Display All Contents of the File";
         cout << "\n 2- Display Content in Reverse Order";
         cout << "\n 3- Display from Point A to Point B";
         cout << "\n 4- Display from Point B to Point A";
         cout << "\n 5- Exit";
	     cout << "\n\n Enter your choice: ";
	     cin >> choice; 
    } 
    


   void ReadFile(ifstream& inFile)
   {
        char byte;
        
	    inFile.clear();
	
        cout<< "\nReading contents from the file:" <<endl;
        if(inFile)
        {
             inFile.get(byte);
             while(inFile.good())
             {
                  cout << byte;
                  inFile.get(byte);  
             }
         }
         inFile.close();
    }
                        

   void BackwardFile(ifstream& inFile)
   {
        char byte;
        
        inFile.clear();
        cout<< "\nReading contents backwards from the file:" <<endl;
        
        inFile.seekg(0L, ios::end);
        
        while(inFile)
        {
             inFile.get(byte);               
             cout << byte;
             inFile.seekg(-1L, ios::cur);  
        }
        inFile.close();
    }
text file contents:

Terri Pinon 95 A
John Doe 80 B
Jack Johnson 75 C
Natalie Smith 90 A
Chris Shaw 70 C
Tim Thomas 100 A
Corey Jones 92 A
Anthony Hill 85 B
Jerry Culpepper 86 B
Bill Moon 73 C
Jen Lowell 70 C
Nick Brown 99 A
Timothy Bell 89 B
John Mallek 50 F
Clint Eastwood 68 D
Michelle Norris 84 B
Sally Fields 96 A
Jason Bourne 100 A
Melody Swift 83 B
Thomas Iban 70 C
inFile.seekg(0L, ios::end);
You're setting the "cursor" position to the very end of the file. All input operations will fail.

1
2
3
4
5
6
        while(inFile)
        {
             inFile.get(byte);               
             cout << byte;
             inFile.seekg(-1L, ios::cur);  
        }

You read 1 byte, then set the "cursor" position back 1 byte. You'll just keep reading the same byte.
I'm going another route here. I can't get this to work either. I'm getting the count ok in numBytes, but then can't read backwards from that position. Can someone please suggest a fix?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 #include <iostream>
#include <string>
#include <iomanip>
#include <istream>
#include <math.h>
#include <fstream>

using namespace std;

const int SIZE = 20;                     
typedef char String[SIZE];

//prototypes
void Menu(int &);
void ReadFile(ifstream &);
void BackwardFile(ifstream &,long &);
long CountFile(ifstream &,long &);


int main()
 {  
    char filename[]= "grades.txt";
    int choice;
    long numBytes;
    
    ifstream InList;
    InList.open(filename);
    
    if(InList.good())
    {
         do
         {         
         Menu(choice); 
         switch(choice)
        	{
            case 1:  
                   ReadFile(InList);
                   break;
            case 2:
                   CountFile(InList,numBytes);
                   BackwardFile(InList,numBytes);
                   break;
            case 3:
                   cout << "Pick a start position between 0 - " << numBytes << endl;
                   break;
            /*case 4:*/
            
            case 5:
                   cout << "\n GOOD BYE." << endl << endl; 
                   break;
            }
         
         }while (choice != 5);                         
    }
	else
         cout << "File did not open successfully." << endl << endl;
          
          
    system("PAUSE");
    return EXIT_SUCCESS;

}
 
 
    void Menu(int &choice) 
    { 
         cout << "\n    Choose an option:";
	     cout << "\n...................................";
         cout << "\n 1- Display All Contents of the File";
         cout << "\n 2- Display Content in Reverse Order";
         cout << "\n 3- Display from Point A to Point B";
         cout << "\n 4- Display from Point B to Point A";
         cout << "\n 5- Exit";
	     cout << "\n\n Enter your choice: ";
	     cin >> choice; 
    } 


   void ReadFile(ifstream& inFile)
   {
        char byte;
        
	    inFile.clear();
	
        cout<< "\nReading contents from the file:" <<endl;
        if(inFile)
        {
             inFile.get(byte);
             while(inFile.good())
             {
                  cout << byte;
                  inFile.get(byte);  
             }
         }
         inFile.close();
    }
                        
   

   void BackwardFile(ifstream& inFile, long& numBytes)
   {
        char byte;
        
        inFile.clear();
        cout<< "\nReading contents backwards from the file:" <<endl;
        
        inFile.seekg(numBytes, ios::end);
        
        while(inFile)
        {
             inFile.get(byte);               
             cout << byte;
             numBytes--;
             inFile.seekg(numBytes);  
        }
        inFile.close();
    }
inFile.seekg(numBytes, ios::end);

The standard does not guarantee that this will work correctly on a file opened in "text" mode.

Read the characters in the file into a vector first, and iterate backwards in the vector.
Simplified code would be something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>

void print_backwards( const char* file_name, long from )
{
    std::vector<char> contents ;
    {
        std::ifstream file(file_name) ;
        char c ;
        while( file.get(c) ) contents.push_back(c) ;
    }

    for( long i = std::min( from, long( contents.size()-1 ) ) ; i >= 0 ; --i )
        std::cout << contents[i] ;

}

int main()
{
    print_backwards( __FILE__, 200 ) ;
}
I experimented a little bit with this. I found certain sequences of operations result in the fail() flag being set. There are several solutions (and I don't know which is best). One is to clear the flags before the seekg().

But here are a couple of other versions I tried:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void BackwardFile(ifstream& inFile, long& numBytes)
{
    char byte;

    inFile.clear();
    std::cout<< "\nReading contents backwards from the file:" << std::endl;

    inFile.seekg(numBytes, ios::beg);

    while (inFile)
    {
         inFile.get(byte);
         std::cout << byte;
         numBytes--;
         inFile.seekg(numBytes, ios::beg);
    }
    
    inFile.close();
}


and this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void BackwardFile(ifstream& inFile, long& numBytes)
{
    char byte;

    inFile.clear();
    std::cout<< "\nReading contents backwards from the file:" << std::endl;

    inFile.seekg(numBytes, ios::end);

    while (inFile)
    {
         byte = inFile.peek();
         std::cout << byte;
         inFile.seekg(-1, ios::cur);
    }

    inFile.close();
}


Hint, if you use a debugger, examine the state of the flags as you step through the code:
1
2
3
4
inFile.good()
inFile.bad()
inFile.fail()
inFile.eof()

we haven't learned vectors in class yet, so I can't use them, unfortunately. we're focusing on seek/tell and file open validation, etc.
> we haven't learned vectors in class yet, so I can't use them, unfortunately.
> we're focusing on seek/tell

In that case, you would want to seek to a position that was not returned by an earlier tellg().
You should open the file in binary mode and not text mode.
Topic archived. No new replies allowed.