有没有办法逐行向后读取文件,而不必从头开始阅读文件开始向后阅读?
答案 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);
}
}
}
编辑:
根据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);
}
答案 2 :(得分:5)
打开要读取的文件,调用fseek()
寻找文件的末尾,然后调用ftell()
以获取文件的长度。或者,您可以致电stat()
或fstat()
将缓冲区指针分配给上面#1中获得的文件大小。
将整个文件读入该缓冲区 - 您可以使用fread()
一次性读取文件(假设文件足够小)。
使用另一个字符指针将文件从缓冲区的末尾横向移动。
答案 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