向后读文件?

有没有一种方法可以逐行读取文件,而不必从头开始读取文件以开始向后读取?

根据评论,一个可能的(相当简单的)替代scheme将被读入vector的行。 例如:

 #include <iostream> #include <fstream> #include <string> #include <vector> int main() { std::ifstream in("main.cpp"); if (in.is_open()) { std::vector<std::string> lines_in_reverse; std::string line; while (std::getline(in, line)) { // Store the lines in reverse order. lines_in_reverse.insert(lines_in_reverse.begin(), line); } } } 

编辑:

根据jrok和Loki Astari的评论, push_back()会更高效,但是行将按照文件顺序排列,所以需要反向迭代( reverse_iterator )或std::reverse()

  std::vector<std::string> lines_in_order; std::string line; while (std::getline(in, line)) { lines_in_order.push_back(line); } 

使用内存映射文件并向后走。 操作系统将以相反的顺序在文件的所需部分中进行分页。

  1. 打开文件进行读取,调用fseek()来查找文件的末尾,然后调用ftell()来获取文件的长度。 或者你可以通过调用stat()fstat()来获得文件长度

  2. 分配一个缓冲区指针,指向上面#1中获得的文件大小。

  3. 将整个文件读入缓冲区 – 你可以使用fread()来一次性读取文件(假设文件足够小)。

  4. 使用另一个字符指针将文件从缓冲区的结尾移到开头。

简短的答案是否定的。 但是,您可以使用seek()函数将指针移动到您想要的位置。 然后从这一点读取()一些数据。 如果您知道如何pipe理缓冲区,那么它应该非常快,因为您可以读取和caching数据,然后search以前的换行符。 玩转\ r \ n将被倒置…

– 更新:对可能的algorithm进行一些阐述 –

这不是有效的代码,但它应该给你一个我想在这里说的东西的想法

文件读取:

 int fpos = in.size() - BUFSIZ; char buf[BUFSIZ]; in.seek(fpos); in.read(buf, BUFSIZ); fpos -= BUFSIZ; // repeat until fpos < 0, although think of size % BUFSIZ != 0 // now buf has characters... reset buffer position int bpos = BUFSIZ - 1; 

获取string:

 // first time you need to call the read if(bpos == -1) do_a_read(); // getting string std::string s; while(bpos >= 0 && buf[bpos] != '\n') { s.insert(0, 1, buf[bpos]); --bpos; } // if bpos == -1 and buf[0] != '\n' then you need to read another BUFSIZ chars // and repeat the previous loop... // before leaving, skip all '\n' while(bpos >= 0 && buf[bpos] == '\n') { --bpos; } return s; 

为了缓解'\ r',你可以进行第一遍转换,将所有'\ r'转换为'\ n'。 否则,所有'\ n'的testing也需要testing'\ r'。

稍微改进的版本将是这样的: –
1)寻find最后一个位置
2)获得最后一个位置
3)读一个字符并打印出来;
4)寻找2后面;
5) last-1次重复3&4;

 ifstream in; in.open("file.txt"); char ch; int pos; in.seekg(-1,ios::end); pos=in.tellg(); for(int i=0;i<pos;i++) { ch=in.get(); cout<<ch; in.seekg(-2,ios::cur); } in.close();