基本上,我需要打开并读取从另一个命令获取的文件列表。 对于 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/