如何使fread阻塞并读取直到结尾? [英] How to make fread blocking and read until the end?

查看:578
本文介绍了如何使fread阻塞并读取直到结尾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用proc_open从PHP执行TCL脚本.

I am executing a TCL script from PHP using proc_open.

  1. 我首先打开TCL外壳 2)使用fwrite发送命令 3)我需要的是等待/阻止直到 fwrite发送的命令已完成 并获取所有内容.该命令可能需要一些时间才能完成. (我只能读取两行,然后转到下一个循环)
  1. I first open the TCL shell 2) Send a command using fwrite 3) What I need is fread to wait/block until the command sent by fwrite is complete and get all the contents .The command may take some time to complete. (I am able to read just 2 lines and then it is going off to the next loop)

有人可以引导我吗?

当前代码为

<?php

$app = 'tclsh84';
$descriptorspec = array(
0 => array("pipe","r"),
1 => array("pipe","w"),
2 => array("file","C:/wamp/www/tcl/bin/g.txt","w")
) ;
$process = proc_open($app, $descriptorspec, $pipes);
if (is_resource($process)) 
{


for($i=0;$i<4;$i++)
{

 fwrite($pipes[0], 'source c:/wamp/www/tcl/bin/test.tcl'."\n");
$content= fread($pipes[1],8192)
print "$content";

}    
   fclose($pipes[0]);    

   fclose($pipes[1]);


   proc_close($process);
}
?>

推荐答案

我正在考虑组合

  • stream_select and/or feof()
  • fread() and concatenation of the partial results ($result .= fread())
  • and maybe proc_get_status() to determine the end of the process

您要等到tcl应用程序在一定时间内没有向其stdout中写入内容(假设这意味着最后一条命令的末尾),然后将下一条命令/行发送到其stdin吗?

You want to wait until the tcl application doesn't write something to its stdout for a certain amount of time (presuming that this means the end of the last command) and then send the next command/line to its stdin?


似乎就像您可以一次将所有命令发送到tcl shell一样,并且它们被一个接一个地处理,即,当对前一个输入/命令执行完后,shell读取下一个输入行/命令.我已经使用脚本对此进行了测试.

edit:
Seems like you can send all commands to the tcl shell at once and they are processed one by one, i.e. the shell reads the next input line/command when it's done with the previous one. I've tested this with the script.

incr a 1
after 1000
puts [concat [clock seconds] $a]

<?php
$app = 'c:/programme/tcl/bin/tclsh85.exe';
$descriptorspec = array(
  0 => array("pipe","r"),
  1 => array("pipe","w"),
  2 => array("file","C:/god.txt","w")
) ;
$process = proc_open($app, $descriptorspec, $pipes);
if (is_resource($process)) {
  fwrite($pipes[0], "set a 1\n");
  for($i=0;$i<4;$i++) {
    fwrite($pipes[0], "source c:/helloworld.tcl\n");
  }
  // when all scripts are done the shell shall exit
  fwrite($pipes[0], "exit\n");
  fclose($pipes[0]);

  do {
    $read=array($pipes[1]); $write=array(); $except=array($pipes[1]);
    // wait up to 1 second for new output of the tcl process
    $ready = stream_select($read, $write, $except, 1, 0);
    if ( $ready && $read /* is not empty */) {
      // get the partial output
      $r = fread($pipes[1], 2048);
      echo $r;
    }
    // is the process still running?
    $status = proc_get_status($process);
  } while($status['running']);
  fclose($pipes[1]);
  proc_close($process);
}
?>

您可能想添加更多错误处理.例如.如果stream_select()返回x次超时,则可能出了问题.

You probably want to add some more error handling. E.g. if stream_select() returns x times with an timeout something might have gone wrong.

edit2:
让shell在每个脚本之后打印一些您可以扫描的内容.

edit2:
Let the shell print something you can scan for after each script.

<?php
// something that's not in the "normal" output of the scripts
$id = 'done'. time();

$app = 'c:/programme/tcl/bin/tclsh85.exe';
$descriptorspec = array(
  0 => array("pipe","r"),
  1 => array("pipe","w"),
  2 => array("file","C:/god.txt","w")
) ;
$process = proc_open($app, $descriptorspec, $pipes);
if (is_resource($process)) {
  fwrite($pipes[0], "set a 1\n");
  for($i=0;$i<4;$i++) {
    $output = '';
    $continue = true;
    $cTimeout = 0;
    echo 'loop ', $i, "\n";
    fwrite($pipes[0], "source c:/helloworld.tcl\n");
    fwrite($pipes[0], "puts $id\n");
    echo "waiting for idle\n";
    do {
      $read=array($pipes[1]);
      $write=array();
      $except=array($pipes[1]);
      $ready = stream_select($read, $write, $except, 1, 0);
      if ( $ready && $read ) {
        $output .= fread($pipes[1], 2048);
        // if the delimiter id shows up in $output
        if ( false!==strpos($output, $id) ) {
            // the script is done
          $continue = false;
        }
      }
    } while($continue);
    echo 'loop ', $i, " finished\n";
  }
  proc_close($process);
}
?>

这篇关于如何使fread阻塞并读取直到结尾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆