C ++ Reading file back from end of file

I am trying to write a program with a menu that reads from a text file in several ways. I'm just working on menu option No. 2 (reading back from the end of the file), but I can't wrap my head in what I'm doing wrong. I have been doing this for several days now and simply cannot find any good resources to help with this. Any help would be appreciated.

#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(); } long CountFile(ifstream& inFile, long& numBytes) { inFile.seekg(0L, ios::end); numBytes = inFile.tellg(); return numBytes; } 
+4
source share
3 answers

The following is my solution to the question. When I open the file, I use ios :: ate to set the position of the file to the end of the file and use the seekg method to read. I am not sure if there is a more efficient way to resolve this issue.

 void readFile(char *fileName){ char c; std::ifstream myFile(fileName,std::ios::ate); std::streampos size = myFile.tellg(); for(int i=1;i<=size;i++){ myFile.seekg(-i,std::ios::end); myFile.get(c); printf("%c\n",c); } } 
+7
source

ios::end does not actually indicate that seekg should look back; rather, it simply indicates that offsets refer to the end of the file. (Yes, I think this is a bad naming convention to call the ios_base::seekdir class.) As far as I know, there is no standard way to actually read the file back, although there are a few suggestions here how to emulate this: Read the file back?

+1
source

If your main intention is to spend time, you want to find the correct position, read the file in the opposite direction, and then cancel the data in memory. If you are reading a large amount and want only a small amount of memory at a time, you can change this a bit to read (for example) 16 or 64 Kilobyte snippets.

Once you have a piece of data in memory, you have two options. You can handle it from end to back to start, or you can undo it and then process it from start to end. The latter may look something like this:

 // Warning: I have only tested this, not proven it correct. std::vector<char> read_backwards(std::istream &is, int size) { std::vector<char> buffer; buffer.resize(size); is.seekg(-size, std::ios::end); is.read(&buffer[0], size); std::reverse(buffer.begin(), buffer.end()); return buffer; } 

Attempting to actually read the file backwards can (and often will) lead to a serious performance issue. To be specific, the standard library often flushes its buffers every time it searches the stream, so every read immediately after the search usually results in a kernel function call to read data from disk (or at least from the OS cache).

If you care about why this is so: the C ++ standard bases its description of how files work on the C standard. The C standard says that if you open a stream for reading and writing, you need to look for a search in the stream when / if you switch from read to write (or vice versa). Because of this, quite a few search implementations in the stream clear the buffer for each search, just in case you can switch from write to read and you need to read the data that was in the write buffer before the search.

Usually this does not really matter: the search will often go beyond the range that is in the buffer, so you still have to read data from disk. However, in the specific case discussed here, buffering can work quite well while you read the data β€œforward” and then cancel it, rather than performing a search for each byte. Although it is best to use the largest buffer that is practical, even a fairly small buffer can make a big difference in speed.

0
source

All Articles