c++ - 从 popen 到 ifstream.open 的文件输出列表

标签 c++ popen ifstream

基本上,我需要打开并读取从另一个命令获取的文件列表。 对于 popen 的每一行输出 使用 ifstream.open 打开文件

它会编译,如果我直接输入文件名,它可以正常工作,但在使用 popen 输出时它不会执行任何操作。我见过这样的问题,但没有见过这种给出文件名的特殊方式。

代码如下:

#include <iostream>
#include <sqlite3.h>
#include <stdio.h>
#include <fstream>

using namespace std;


int main () {

    ifstream singlefile;
    FILE *filelist;
    char filename[512];
    string progline;

    if(!(filelist = popen("find `pwd` -name \"*.js\"", "r"))){
        return 1;
    }

    while( fgets(filename, sizeof(filename), filelist)!=NULL)
    {
        cout << filename;
        singlefile.open(filename, ifstream::in);
        while ( singlefile.good() )
        {
            getline (singlefile,progline);
            cout << progline << endl;
        }

        singlefile.close();
    }

    pclose(filelist);

  return 0;

}

下一步不会在循环内打开每个文件,而是存储文件列表,然后打开每个文件。

谢谢

最佳答案

fgets 保留尾随换行符,导致文件名不存在。此外,流状态仅在读取后更新。如果我用以下代码替换 while 主体,它对我有用:

  cout << filename;
  size_t len = strlen(filename);
  // chop off trailing newline
  if (len > 1 && filename[len - 1] == '\n') filename[len - 1] = 0;
  singlefile.open(filename, ifstream::in);
  while ( getline(singlefile, progline) )
    {
      cout << progline << endl;
    }

  singlefile.close();

如果您确实想遍历文件列表,我会使用 Boost.Filesystem ,它有一个很好的 C++ 接口(interface),适用于所有文件名(甚至是带有换行符的文件名),并且与平台无关。

如果这实际上只是一个示例,并且您的实际命令不是 find,那么仍有一些简化的空间。这是使用 Boost.Iostreams 的建议摆脱大部分 C 函数调用(如果有一个设备源从进程的标准输出读取,那就太好了,但 Boost.Iostreams 缺少这一点):

#include <cstdio>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>

#include <stdio.h>

#include <boost/noncopyable.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

using namespace std;
namespace io = boost::iostreams;

class Popen: private boost::noncopyable {
public:
  explicit Popen(const char* command):
    m_stream(popen(command, "r")) {
    if (!m_stream) throw runtime_error("popen failed");
  }

  ~Popen() {
    pclose(m_stream);
  }

  FILE* stream() const {
    return m_stream;
  }

private:
  FILE* m_stream;
};


int main() {
  Popen pipe_wrapper("find `pwd` -name \"*.cpp\"");
  io::file_descriptor_source pipe_device(fileno(pipe_wrapper.stream()), io::never_close_handle);
  io::stream<io::file_descriptor_source> pipe_stream(pipe_device, 0x1000, 0x1000);
  string filename;
  while (getline(pipe_stream, filename)) {
    cout << filename << endl;
    ifstream file_stream(filename.c_str(), ifstream::in);
    string progline;
    while (getline(file_stream, progline)) {
      cout << progline << endl;
    }
  }
}

关于c++ - 从 popen 到 ifstream.open 的文件输出列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9591963/

相关文章:

c++ - 是否可以将一个类的所有数据成员和方法都设置为静态来设计单例?

c - popen/pclose 的替代品?

使用 popen 时找不到命令

C++ 如何为 ifstream 成员正确使用 getline

c++ - 为什么只有 random-access-iterator 在 C++ 中实现 operator+?

c++ - FFmpeg:做一个应用程序比直接使用ffmepg更好吗

c++ - std::make_shared 三元返回不编译

Python 使用 Popen 的子进程超时

c++ - 读取/写入 outfile 错误(可能是简单的修复)

c++ - 文件输入和编译错误