对于我在 Linux 中实现 tail shell 命令,我需要使用流输入/输出从文件末尾读取一定数量的行/字节。有没有人有建议如何做到这一点?我怀疑我需要打开一个文件并将一些参数传递给 ifstream 构造函数,但我不知道究竟是什么。谷歌搜索没有找到任何东西。
问问题
395 次
5 回答
4
由于 tail 需要使用管道,因此您无法倒带,因此您必须保留您已阅读的最后 n 行的旋转缓冲区,您将在 EOF 上转储。
于 2010-01-17T20:30:33.877 回答
3
这个问题类似于获取n
单链表的最后一个节点的问题。您必须使用一行缓冲区一直走到最后n
,然后从缓冲区中吐出这些行。
于 2010-01-17T20:31:40.617 回答
2
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
ifstream is("file.txt", ios::binary);
if (!is) {
cout << "Failed to open file" << endl;
return 1;
}
is.seekg(0, ios::end);
int len = is.tellg();
char c;
int n = 0;
ostringstream line;
int lines = 0;
for (int i = len - 1; i >= 0; --i) {
is.seekg(i, ios::beg);
is.get(c);
if (c == '\n' || i == 0) {
if (i < len - 1) {
if (i == 0) {
line << c;
}
string s = line.str();
cout << lines << ": " << string(s.rend() - n, s.rend()) << endl;
++lines;
n = 0;
line.seekp(0, ios::beg);
}
} else {
line << c;
++n;
}
}
is.close();
return 0;
}
于 2010-01-17T20:27:27.807 回答
2
我不认为有一个简单的方法来解决这个问题,你可能需要寻找到文件的末尾,备份一个“块”(任意大小,但可能是几千字节),读到'块”数据并开始在其中查找换行符,如果找不到足够的数据,则备份两倍的块大小(请记住,您是向前阅读的,因此您需要备份您读取的那个,再加上一个你想读下一个),然后读另一个。
高温高压
于 2010-01-17T20:27:39.303 回答
0
这显示了您如何在 C++ 中执行此操作...从文件末尾读取连续的块,然后扫描这些块以查找新行。如果没有找到换行符,则必须保留部分块并与读入的下一个块结合...
//
// USAGE: lastln COUNT [FILE]
//
// Print at most COUNT lines from the end of FILE or standard input.
// If COUNT is -1, all lines are printed.
//
#include <errno.h>
#include <libgen.h>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(int argc, char **argv)
{
int ret = 0, maxLines = -1, len, count = 0, sz = 4096, lines = 0, rd;
istream *is;
ifstream ifs;
stringstream ss;
char *buf = NULL;
const char *prog = (argc > 0 && argv[0] ? basename(argv[0]) : "");
string line;
if (argc > 1) {
if ((maxLines = atoi(argv[1])) == 0) {
goto end;
}
}
if (argc > 2 && !(argv[2] && argv[2][0] == '-' && argv[2][1] == '\0')) {
ifs.open(argv[2], ios::in | ios::binary);
if (!ifs) {
ret = 1;
cerr << prog << ": " << argv[2] << ": " << strerror(errno) << endl;
goto end;
}
is = &ifs;
} else {
ss << cin.rdbuf();
if (!ss) {
ret = 1;
cerr << prog << ": failed to read input" << endl;
goto end;
}
is = &ss;
}
is->seekg(0, ios::end);
len = is->tellg();
buf = new char[sz + 1];
while (rd = min(len - count, sz)) {
is->seekg(0 - count - rd, ios::end);
is->read(buf, rd);
count += rd;
char *p = buf + rd, *q;
*p = '\0';
for (;;) {
q = (char *)memrchr(buf, '\n', p - buf);
if (q || count == len) {
if (q) *q = '\0';
if (lines || p - q - 1 > 0 || !q) {
++lines;
cout << lines << ": " << (q ? q + 1 : buf) << line << endl;
line.clear();
if (lines >= maxLines && maxLines != -1) break;
}
if (q) p = q; else break;
} else {
line = string(buf, p - buf) + line;
break;
}
}
}
end:
if (buf) delete[] buf;
return ret;
}
于 2010-01-18T01:28:17.990 回答