向后读一个文件?

时间:2012-05-30 09:53:41

标签: c++

有没有办法逐行向后读取文件,而不必从头开始阅读文件开始向后阅读?

6 个答案:

答案 0 :(得分:12)

使用memory-mapped file然后向后走。操作系统将以相反的顺序在文件的所需部分中进行分页。

答案 1 :(得分:8)

根据评论,可能(非常简单)的替代方案是将行读成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);
        }
    }
}

编辑:

根据jrokLoki 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);
    }

答案 2 :(得分:5)

  1. 打开要读取的文件,调用fseek()寻找文件的末尾,然后调用ftell()以获取文件的长度。或者,您可以致电stat()fstat()

  2. 来获取文件长度
  3. 将缓冲区指针分配给上面#1中获得的文件大小。

  4. 将整个文件读入该缓冲区 - 您可以使用fread()一次性读取文件(假设文件足够小)。

  5. 使用另一个字符指针将文件从缓冲区的末尾横向移动。

答案 3 :(得分:3)

简短的回答是否定的。但是,您可以使用seek()函数将指针移动到您想去的位置。然后从那一点读取()一些数据。如果您非常清楚如何管理缓冲区,那么它应该非常快,因为您可以读取和缓存数据,然后搜索以前的换行符。享受\ r \ n的乐趣,它将被颠倒......

- 更新:对可能的算法进行一些阐述 -

这不是有效的代码,但它应该让你知道我在这里想说的是什么

文件读取:

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;

获取字符串:

// 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'的所有测试都需要测试'\ r'。

答案 4 :(得分:3)

略有改进的版本将是: -
1)寻找最后一个位置
2)获得最后1位置 3)读取一个字符并打印出来;
4)寻找2位回位;
5)重复3&amp; 4 last-1次;

    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();

答案 5 :(得分:0)

我的答案类似于使用vector存储文件行的答案,但是我将使用list

假设您在名为input.txt的文件中包含以下文本:

hello
there
friend

我会逐行读取文件,将每一行都推到list的后面而不是它的前面。使用此功能而不是使用push_back的效果与将文件内容逐行读取到vector中,然后将其反转或向后迭代的效果相同。

#include <iostream>
#include <fstream>
#include <list>
#include <string>
#include <iterator>
#include <algorithm>

int main(void) {
    std::ifstream file;
    file.open("input.txt");
    // Make sure the file opened properly

    std::list<std::string> list;
    std::string buffer;
    while (std::getline(file, buffer)) {
        list.push_front(buffer);
    }

    file.close();

    std::copy(
        list.begin(),
        list.end(),
        std::ostream_iterator<std::string>(std::cout, "\n")
    );

    return 0;
}

(请注意,std::copy底部的位置只是用换行符作为元素之间的分隔符来打印列表的内容。)

然后打印:

friend
there
hello
相关问题