Как получить несколько результатов из файла, открытого только один раз, с помощью proc_open?

У меня есть команда, запускаемая с помощью exec(), которая возвращает значение из очень большого файла данных, но ее нужно запускать миллионы раз. Чтобы избежать открытия файла каждый раз в цикле, я хочу перейти к решению на основе proc_open, где указатель файла создается один раз для эффективности, но не могу понять, как это сделать.

Вот версия на основе exec, которая работает, но работает медленно, предположительно потому, что ей приходится открывать файл на каждой итерации:

foreach ($locations as $location) {
    $command = "gdallocationinfo -valonly -wgs84 datafile.img {$location['lon']} {$location['lat']}";
    echo exec ($command);
}

Моя попытка создать код на основе proc_open выглядит следующим образом:

$descriptorspec = array (
    0 => array ('pipe', 'r'),  // stdin - pipe that the child will read from
    1 => array ('pipe', 'w'),  // stdout - pipe that the child will write to
    // 2 => array ('file', '/tmp/errors.txt', 'a'), // stderr - file to write to
);

$command = "gdallocationinfo -valonly -wgs84 datafile.img";
$fp = proc_open ($command, $descriptorspec, $pipes);

foreach ($locations as $location) {
    fwrite ($pipes[0], "{$location['lon']} {$location['lat']}\n");
    fclose ($pipes[0]);
    echo stream_get_contents ($pipes[1]);
    fclose ($pipes[1]);
}

proc_close ($fp);

Это правильно получает первое значение, но затем генерирует ошибку для каждой последующей итерации:

3.3904595375061 

Warning: fwrite(): 6 is not a valid stream resource in file.php on line 11
Warning: fclose(): 6 is not a valid stream resource in file.php on line 12
Warning: stream_get_contents(): 7 is not a valid stream resource in file.php on line 13
Warning: fclose(): 7 is not a valid stream resource in file.php on line 14

Warning: fwrite(): 6 is not a valid stream resource in file.php on line 11
...

person fooquency    schedule 25.09.2015    source источник
comment
Похоже, что gdallocationinfo закрывает свой поток stdin после возврата первого результата. Вы уверены, что этот тип использования поддерживается gdallocationinfo?   -  person peaceman    schedule 25.09.2015


Ответы (1)


  1. Вы не «открываете файл», вы выполняете процесс. Если этот процесс не предназначен для обработки нескольких запросов в рамках одного выполнения, вы не сможете обойти это с помощью proc_open() или чего-либо еще.
  2. В следующем блоке вы закрываете как входной, так и выходной каналы процесса, и все же вы удивлены, когда больше не можете читать или писать?

    foreach ($locations as $location) {
        fwrite ($pipes[0], "{$location['lon']} {$location['lat']}\n");
        fclose ($pipes[0]); // here
        echo stream_get_contents ($pipes[1]);
        fclose ($pipes[1]); // and here
    }
    

    Попробуйте не этого делать.

person Sammitch    schedule 25.09.2015