Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用C+中的流从文件末尾读取给定数量的行+;?_C++_Linux_Inputstream - Fatal编程技术网

C++ 如何使用C+中的流从文件末尾读取给定数量的行+;?

C++ 如何使用C+中的流从文件末尾读取给定数量的行+;?,c++,linux,inputstream,C++,Linux,Inputstream,为了在Linux中实现tail shell命令,我需要使用流输入/输出从文件末尾读取一定数量的行/字节。有人对如何做到这一点有什么建议吗?我怀疑我需要打开一个文件并将一些参数传递给ifstream构造函数,但我不知道具体是什么。谷歌搜索没有找到任何东西。#包括 #include <iostream> #include <fstream> #include <sstream> using namespace std; int main() { ifstr

为了在Linux中实现tail shell命令,我需要使用流输入/输出从文件末尾读取一定数量的行/字节。有人对如何做到这一点有什么建议吗?我怀疑我需要打开一个文件并将一些参数传递给ifstream构造函数,但我不知道具体是什么。谷歌搜索没有找到任何东西。

#包括
#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;
}
#包括 #包括 使用名称空间std; int main() { ifstream是(“file.txt”,ios::binary); 如果(!is){
cout我认为没有一种简单的方法可以做到这一点,您可能需要查找到文件的末尾,备份一个“块”(任意大小,但可能有几千字节),读取该“块”数据并开始查找新行字符,如果找不到足够的字符,则备份两倍于块大小(记住,你是向前读的,所以你需要备份你读过的,加上下一个你想读的),然后读入另一个


HTH

由于tail需要与管道一起工作,您不能倒带,因此您必须保留读取的最后n行的旋转缓冲区,并将其转储到EOF。

此问题类似于获取单个链接列表的最后
n
节点的问题。您必须使用
n的缓冲区一直到最后行,然后从缓冲区吐出行。

这显示了C++中如何做…从文件的结尾读取连续块,然后扫描块以获取新的行。如果没有找到换行符,则必须保留块的一部分,并与下一个块在……/p>中结合。
//
// 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;
}
//
//用法:lastln计数[文件]
//
//从文件结尾或标准输入最多打印计数行。
//如果计数为-1,则打印所有行。
//
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int main(int argc,字符**argv)
{
int-ret=0,maxLines=-1,len,count=0,sz=4096,lines=0,rd;
istream*是;
国际单项体育联合会;
细流ss;
char*buf=NULL;
常量char*prog=(argc>0&&argv[0]?basename(argv[0]):“”);
弦线;
如果(argc>1){
if((maxLines=atoi(argv[1]))==0){
转到终点;
}
}
如果(argc>2&&!(argv[2]&&argv[2][0]='-'&&argv[2][1]='\0')){
ifs.open(argv[2],ios::in | ios::binary);
如果(!ifs){
ret=1;

cerr标准库与此无关-您必须编写一些代码。要实现tail的-f标志,您必须使用一些非标准的东西。流不是为此而设计的。流用于序列化(文本数据的非序列化)。使用类似C的代码会更容易。这种方法适用于短文件。但大文件需要不同的技术。您需要寻找到最后,然后开始备份。您可以对不同的文件使用不同的技术,但我描述的技术对于stdin等东西仍然是必需的。此外,作业不需要执行良好,至少,他没有说是这样。向后查找文件的开头(即,如果文件大小小于4096字节)实际上是未定义的。该程序使用指针和手动内存管理是没有原因的。该程序也可以使用std::vector来动态分配数据和自动存储std::ifstream,而不是指针和动态分配。这避免了最后的所有清理,从而也避免了使用goto。它还避免了内存泄漏。n你需要一个指针,它有一个指针。一个向量是一个无意义的间接层。这里使用指针是必要的。你似乎忘记了引用不能在C++中重新存储。GOTO是必需的,这样OP可以在运行结束时打印消息。并且不需要在Ext()之前立即释放数据。任何情况下,你都会困扰语法糖。我称之为“更喜欢读代码”,而不是“语法糖”。这个代码读起来更像C,而不是习惯性C++。你可以得到一个指向“代码> STD::向量< /代码>的内容的指针,用于与<代码> MeMrCHR
,通过调用<代码> Frand()
并获取地址。指针不必使用
cin
;您可以在命令行上同时支持stdin和文件名,而无需使用指针,方法是将代码放在一个函数中,该函数采用
istream&
参数,并将其作为ne传递
std::cin
std::ifstream
实例eded.@Wyzard:您的解决方案需要添加一个不必要的函数和对它的多次调用,以处理指针设计用于使用c++内置多态性解决的问题。您的解决方案不可扩展。如果有两种以上的流类型呢?您创建了冗余分支。您将使用非常长的长度来避免点你承认,即使使用vector,底层指针在任何情况下都是暴露的,所以你仍然在使用指针。