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

时间:2012-03-06 21:10:27

标签: c++ popen ifstream

基本上我需要打开并读取我从另一个命令获得的文件列表。 对于popen的每一行输出  打开文件usen 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;

}

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

由于

1 个答案:

答案 0 :(得分:2)

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 ++接口,适用于所有文件名(即使是那些有换行符的文件名),并且与平台无关。

如果这只是一个示例,而您的实际命令不是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;
    }
  }
}