c++ fastest way to read only last line of text file?

前端 未结 7 487
温柔的废话
温柔的废话 2020-11-27 20:35

I would like to read only the last line of a text file (I\'m on UNIX, can use Boost). All the methods I know require scanning through the entire file to get the last line wh

相关标签:
7条回答
  • 2020-11-27 21:20

    While the answer by derpface is definitely correct, it often returns unexpected results. The reason for this is that, at least on my operating system (Mac OSX 10.9.5), many text editors terminate their files with an 'end line' character.

    For example, when I open vim, type just the single character 'a' (no return), and save, the file will now contain (in hex):

    61 0A
    

    Where 61 is the letter 'a' and 0A is an end of line character.

    This means that the code by derpface will return an empty string on all files created by such a text editor.

    While I can certainly imagine cases where a file terminated with an 'end line' should return the empty string, I think ignoring the last 'end line' character would be more appropriate when dealing with regular text files; if the file is terminated by an 'end line' character we properly ignore it, and if the file is not terminated by an 'end line' character we don't need to check it.

    My code for ignoring the last character of the input file is:

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <iomanip>
    
    int main() {
        std::string result = "";
        std::ifstream fin("test.txt");
    
        if(fin.is_open()) {
            fin.seekg(0,std::ios_base::end);      //Start at end of file
            char ch = ' ';                        //Init ch not equal to '\n'
            while(ch != '\n'){
                fin.seekg(-2,std::ios_base::cur); //Two steps back, this means we
                                                  //will NOT check the last character
                if((int)fin.tellg() <= 0){        //If passed the start of the file,
                    fin.seekg(0);                 //this is the start of the line
                    break;
                }
                fin.get(ch);                      //Check the next character
            }
    
            std::getline(fin,result);
            fin.close();
    
            std::cout << "final line length: " << result.size() <<std::endl;
            std::cout << "final line character codes: ";
            for(size_t i =0; i<result.size(); i++){
                std::cout << std::hex << (int)result[i] << " ";
            }
            std::cout << std::endl;
            std::cout << "final line: " << result <<std::endl;
        }
    
        return 0;
    }
    

    Which will output:

    final line length: 1
    final line character codes: 61 
    final line: a
    

    On the single 'a' file.

    EDIT: The line if((int)fin.tellg() <= 0){ actually causes problems if the file is too large (> 2GB), because tellg does not just return the number of characters from the start of the file (tellg() function give wrong size of file?). It may be better to separately test for the start of the file fin.tellg()==tellgValueForStartOfFile and for errors fin.tellg()==-1. The tellgValueForStartOfFile is probably 0, but a better way of making sure would probably be:

    fin.seekg (0, is.beg);
    tellgValueForStartOfFile = fin.tellg();
    
    0 讨论(0)
提交回复
热议问题