- - PR -
WinXP で InputStream の読取にタイムラグが生じる
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2006-03-28 17:22
お世話になります。
WinXP上でJavaから他のプログラムを起動し、その出力を読み取るプログラムを作っているのですが、その外部プログラムが終了するまでInputStreamのReadが戻ってこない状況になっています。 ソースを見ていただけると分かると思うのですが、起動して20秒たたないと何も表示されない状況になります。 Javaのソース: ExecAt1.java import java.io.*; public class ExecAt1 { public static void main(String[] args) throws Exception { String cmd = "cmd /c D:\\\\temp\\\\test.exe"; byte[] ibuff = new byte[100]; int ilen, alen; Process run = Runtime.getRuntime().exec(cmd); InputStream is = run.getInputStream(); System.out.println("Start\\n"); while(true){ ilen = is.read(ibuff); if( ilen < 0 ) break; System.out.write(ibuff,0,ilen); } System.out.println("End\\n"); } } 外部プログラムのサンプル:test.c #include <stdio.h> int main() { int i; for(i=0;i<10;i++){ printf("%d ======================\\n",i); sleep(2); } exit(0); } | ||||
|
投稿日時: 2006-03-28 17:35
出力側がバッファリングされているのではないでしょうか?
だとしたら flush してあげましょう。 | ||||
|
投稿日時: 2006-04-04 10:41
このJavaから起動する予定のプログラムは実はPerlスクリプトで、
#! /usr/bin/perl $|=1; のように autoflush を用いても解決できませんでした。 同じソースでも Linux では動作するので、Java というより WinXP の差異によるものだと判断しました。 ですのでJavaとしてではなくWindows関連の会議室の方へ再度投稿します。 ありがとうございました。 | ||||
|
投稿日時: 2006-04-04 12:33
read() が返ってこないというのはどうやって確認しましたか?
System.out.write() ではコンソールへの出力はバッファリングされますから、flush() しないと read() が返ってきたかどうか確認にならないと思います。 私の推測では、read() は 10回目までの呼び出しまで正しく返ってきています。ただ、System.out.write() での確認出力がバッファリングされているために、それが確認できていない。また、read() の 11回目の出力はブロックされているでしょう。それは相手プロセスが標準出力(stdout)を閉じていないから、当然といえば当然かと。むしろ、Linux では(プロセス終了前に)標準出力から EOF が返ってくるほうが挙動としては解せないです。 | ||||
|
投稿日時: 2006-04-04 14:55
まず、Perl でも C で書いた EXE でも現象が同じなのですよね。
また、
を見ると、シェル(cmd.exe)を使う必要がありませんので、使わないほうが余計な要素が減って良いと思います。 また、exec メソッドは、引数に空白区切りの文字列を渡すものと、文字列の配列で渡すものがあります。通常は、後者のほうが確実です(たとえば EXE に渡す引数がパス名で、それに空白がある場合等の場合等に顕著)。 flush が効いているのか怪しい場合は、とりあえず、ムダに長めの文字列を100KBほど出力してみるようにしてみてはどうでしょうか。 | ||||
|
投稿日時: 2006-04-04 21:52
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=25599&forum=12 私の以前の投稿ですが参考になりませんでしょうか? 別スレッドにしないと、標準出力がパンクしていたような。 | ||||
|
投稿日時: 2006-04-04 23:39
test.exe の標準出力がバッファリングされているのが原因です。
1行出力する毎にJava側で1行readしたいのなら、printf()する毎にfflush(stdout); する必要があります。 perl なら、$| = 1; で解決できます。 Java側のSystem.out は(出力先がコンソールなら)autoflushになっているので、 改めてflushする必要はありません。 ただ、標準出力の先がパイプの場合にフルバッファリングになるのは Windowsでもunix系でも同じハズなので、linuxで違う挙動をしめすというのは解せません。
この書き方がWindowsで通用するはずないのですが、どうやって確認されたのでしょう? もしかして、Cygwinですか? |
1