简体   繁体   中英

How to read the 6th character from the end of the file - ifstream?

void maintainFileName ()
{
    std :: ifstream myfile;
    myfile.open ("zoomLevels.txt");

    if (myfile.is_open ())
    {
        // Move to end of the file, 
        myfile.seekg (0, std::ios::end);

        // and then six characters back to pick up the last file number.
        myfile.seekg (6, std::ios::beg);

        int len = 1;
        char *t = new char[len];

        myfile.read(t, len);
        qDebug () << "\nt: " << *t << "\n";
    }
    else
    {
        qDebug () << "\nsorry";
    }
}

The file contains this:

78.8115,29.582,1,01.rda
78.8115,29.582,2,02.rda
76.3671,30.2201,1,11.rda
76.3671,30.2201,2,12.rda
78.1908,30.3007,1,01.rda
78.1908,30.3007,2,02.rda
77.3284,29.1415,1,01.rda
77.3284,29.1415,2,02.rda
77.3064,29.1655,1,01.rda
77.3064,29.1655,2,02.rda

The value returned by that function is 5 , whereas the sixth character from the end is 0 !
Where am I going wrong?

Seeking to an arbitrary position in a text file is undefined behavior. In practice, it will probably work under various Unices, but no where else. If you open the file in binary mode, the seek is legal. Formally, if you open the file in binary mode, you may get extra nul bytes at the end, but in practice, this isn't a problem today. If you open it in binary mode, however, you may see something else instead of '\\n' in the data; under Windows, for example, you'll see the two character sequence 0x0D, 0x0A .

Of course, in your code, you're seeking from the beginning, not from the end. This is also undefined behavior, but most of the time, it will work as long as you are seeking in the first line.

And finally, the sixth character from the end in the data you show is a '2' , not a '0' , as you write. But of course, on systems other than Unix, you could easily see something else (or get an error): probably a '.' under Windows, or or an error (or maybe a ' ' ' ) under some mainframe OS.

myfile.seekg (6, std::ios::beg);

here you are moving 6 characters from the begining, not towards the begining. Just use

myfile.seekg (-6, std::ios::end);

The first seek skips to the end and the second one skips to the beginning + 6.

Use:

 myfile.seekg(-6, std::ios::end);

You can try determining the complete size of the file via tellg() at the end of the file and the subtract your numbers, validate it against > 0 and then seek to it again. If you try this, you should also ensure the file is opened in binary mode (I remember, there may be a flaw)

myfile.seekg (0, ios::end);
// You have to ensure, myfile.tellg() > 6
myfile.seekg ( myfile.tellg() - 6, ios:beg );

Edit:

seekg takes the type std::streamoff as the offset.

The Standard (ISO/IEC 14882:2003) says some very interesting things about this "problem" here many people discuss about.

In section 27.2. Forward declarations, the streampos is of class fpos.

If we went further, we can find the requirements table for fpos at section 27.4.3.2, where we can get the closure to the streamoff type, and here an explicit requirement is: q = p + o, so the fpos class MUST DEFINE an operator+( offset). Since the fpos object has also to define a O(p) with return type OFF_T which is a internal type, but there is also a statement, the std::streamoff is of type OFF_T we have a closed loop to a definition inside the standard for this operation.

So this operation should be well defined.

Other opinions are welcome.

First, go to the end of the file: is.seekg (0, ios::end); , then save the position: file_end_position = is.tellg(); . Now jump to that position: is.seekg (file_end_position-6, ios::end); , and read the 6th character from the end: is.read (buf,1);

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  int file_end_position;

  ifstream is;
  is.open ("test.txt", ios::binary );

  // get size of file:
  is.seekg (0, ios::end);
  file_end_position = is.tellg();
  is.seekg (0, ios::beg);


  //go to the end  of the file -6
  is.seekg (file_end_position-6, ios::end);

  char buf[1];

  // read the 6th character from the end of the file  
  is.read (buf,1);
  is.close();



  delete[] buffer;
  return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM