基本上我需要打开并读取我从另一个命令获得的文件列表。 对于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;
}
下一步不会打开循环中的每个文件,而是存储文件列表然后打开每个文件。
由于
答案 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;
}
}
}