Запись вывода popen () в файл - PullRequest
0 голосов
/ 20 января 2011

Я пытался вызвать другую программу из c ++ и сохранить полный текст этой программы в текстовый файл.popen () кажется подходящей функцией, но сохранение ее в текстовый файл не работает.

      ofstream delaunayfile;
    delaunayfile.open ("triangulation/delaunayedpoints.txt");
      FILE *fp;
      fp = popen("qdelaunay < triangulation/rawpoints.txt", "r");
    delaunayfile << fp;
    delaunayfile.close();

Любая помощь?Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 20 января 2011

Вы не можете записать FILE* непосредственно в поток. Он будет записывать адрес памяти вместо фактического содержимого файла, поэтому он не даст вам желаемого результата.

Идеальным решением было бы чтение из ifstream и запись в ваш ofstream, но нет способа построить ifstream из FILE*.

Однако мы можем расширить класс streambuf, заставить его работать над FILE*, а затем вместо этого передать его istream. Быстрый поиск показал, что кто-то уже реализовал это и правильно назвал popen_streambuf. См этот конкретный ответ .

Ваш код будет выглядеть так:

std::ofstream output("triangulation/delaunayedpoints.txt");
popen_streambuf popen_buf;
if (popen_buf.open("qdelaunay < triangulation/rawpoints.txt", "r") == NULL) {
    std::cerr << "Failed to popen." << std::endl;
    return;
}
char buffer[256];
std::istream input(&popen_buf);
while (input.read(buffer, 256)) {
    output << buffer;
}
output.close();

Как указывает Саймон Рихтер в комментариях, есть operator<<, который принимает streambuf и записывает данные в ostream до достижения EOF. Таким образом, код будет упрощен до:

std::ofstream output("triangulation/delaunayedpoints.txt");
popen_streambuf popen_buf;
if (popen_buf.open("qdelaunay < triangulation/rawpoints.txt", "r") == NULL) {
    std::cerr << "Failed to popen." << std::endl;
    return;
}
output << &popen_buf;
output.close();
0 голосов
/ 20 января 2011

popen открывает канал, но я не знаю, что вы можете просто направить его в файл delaunayfile таким образом.

Конечно, было бы очень хорошо, если бы вы могли просто сделать это, и он читал бы из канала добыл завершен.

Обычный способ проверить данные в канале - использовать select ().Я нашел полезную ссылку http://codenewbie.com/forums/threads/2908-Using-std-fstream-in-a-pipe, которая интегрирует каналы с fstream, и может помочь вам достичь того, что вы хотите.

В этом случае, хотя все, что вы хотите сделать, - записать вывод в файлпочему бы не перенаправить вывод процесса на него, а не на канал?Назначение канала - межпроцессное взаимодействие, но ваш процесс, похоже, не использует данные, полученные от другого процесса, для каких-либо практических целей.

0 голосов
/ 20 января 2011

Есть два способа сделать это: простой способ

int rc = system("qdelaunay < triangulation/rawpoints.txt >triangulation/delaunayedpoints.txt");

и немного более сложный способ, используя fork (), dup2 () и execve (), последний работает без интерпретатора оболочкиустановлен в системе.Учитывая, что похоже, что вы выполняете вычислительную работу, я подозреваю, что это не встроенная система, поэтому вы можете использовать работающую оболочку.

...