2013-01-07 95 views
1

我试图写入输出流并读取简单的Autoit脚本的输入流。如果我不使用newLine()字符,我会得到预期的输出:一行发送到自动它,一行发送到java,然后重复。如果我添加newLine()字符,看起来每个周期都会有一个额外的行被发送到autoit。 这是为什么?Java,读写Autoit脚本的输入和输出流

的AutoIt:

Local $line 

While (True) 

    $line = ConsoleRead() 

    ConsoleWrite($line & "to java" & @LF) 

    Sleep(25) 

WEnd 

的Java:

p = Runtime.getRuntime().exec("Test"); 

in = new BufferedReader(new InputStreamReader(p.getInputStream())); 
out = new BufferedWriter(new OutputStreamWriter(p.getOutputStream())); 

int i=0; 

out.write("(" + i++ + ") to autoit"); 
out.newLine(); 
out.flush(); 

while ((line = in.readLine()) != null) { 

    System.out.println(line); 

    out.write("(" + i + ") to autoit"); 
    out.newLine(); 
    out.flush(); 

    if(i++ > 9) 
     p.destroy(); 
} 

输出:

(0) to autoit 
to java 
(1) to autoit 
(2) to autoit 
to java 
(3) to autoit 
(4) to autoit 
(5) to autoit 
to java 
(6) to autoit 
(7) to autoit 
(8) to autoit 
(9) to autoit 
to java 

输出我预计:

(0) to autoit 
to java 
(1) to autoit 
to java 
(2) to autoit 
to java 
(3) to autoit 
to java 
(4) to autoit 
to java 
(5) to autoit 
to java 
(6) to autoit 
to java 
(7) to autoit 
to java 
(8) to autoit 
to java 
(9) to autoit 
to java 
+0

+1有趣的问题!我注意到,当我们进行更多的迭代时,我们总是将+1行设置为“autoit”,就像在输出中已经看到的一样。 – mrt

回答

1

我不是专家在此,不以任何方式,但考虑到这些变化:

  • 用的AutoIt的ConsoleRead()的一个问题是,它没有阻止和我相信不承认新的路线。换句话说,它的行为不像Java的Scanner.nextLine()。
  • 它实际上可能会一次读取大量的线条,我不确定这是否可以预测。
  • 考虑使用的AutoIt的StringSplit(...)功能,以分割出使用@CRLF作为分隔符线,然后推动使用ConsoleWrite(...)
  • 所得阵列的标准列于每个String考虑具有的AutoIt使用StringInStr(...)函数来测试的令牌告诉它退出。
  • 在Java方面,我认为你需要在一个单独的线程中读取标准文本中的文本,以避免被阻塞。
  • 我已经使用Scanner解析标准,并且像使用PrintStream一样轻松输出到标准输出。

例如:

EchoCaller2.java

import java.io.BufferedOutputStream; 
import java.io.IOException; 
import java.io.PrintStream; 
import java.util.Scanner; 

public class EchoCaller2 { 
    private static final String AUTO_IT_ECHOER = "Echoer.exe"; // AutoIt program 
    private static Scanner scan = null; 
    private static PrintStream out = null; 

    public static void main(String[] args) throws IOException, 
     InterruptedException { 
     ProcessBuilder pb2 = new ProcessBuilder(AUTO_IT_ECHOER); 
     pb2.redirectErrorStream(); 
     Process p = pb2.start(); 
     scan = new Scanner(p.getInputStream()); 
     out = new PrintStream(new BufferedOutputStream(p.getOutputStream())); 

     new Thread(new Runnable() { 
     public void run() { 
      while (scan.hasNextLine()) { 
       System.out.println(scan.nextLine()); 
      } 
      scan.close(); 
     } 
     }).start(); 

     for (int i = 0; i < 10; i++) { 
     out.println("(" + i + ") to autoit "); 
     out.flush(); 
     } 

     out.println("exit "); 
     out.flush(); 
     out.close(); 
    } 
} 

Echoer.au3

Local $line 

While (True) 

    $line &= ConsoleRead() 

    $strArray = StringSplit($line, @CRLF) 

    If $strArray[0] > 0 Then 
     For $r = 1 to $strArray[0] 
      If StringLen($strArray[$r]) > 0 Then 
       ConsoleWrite($strArray[$r] & "to java" & @CRLF) 
      EndIf 
     Next 
    EndIf 

    If StringInStr($line, "exit") Then 
     Exit 
    EndIf 

    $line = "" 

    Sleep(25) 

WEnd 
+1

+1。事实上,这可以获得预期的产出。张贴后我玩了很多。我可以让事情间接工作,并最终做到这一点(事实上,在@CRLF中完全一样的StringSplit)我仍然不知道为什么我必须这样做。最终,我循环了标准的新行字符,然后每个不可打印的字符,以确保。这个问题肯定是ConsoleRead()的不可预测性。非常感谢,我现在要解决这个问题,只是为了确保一个java-autoit专家不会看到它:)但我相信这将是公认的答案。 – roundar

+0

@roundar:我认为问题在于每次调用标准输入缓冲区时,ConsoleRead()都会读取它。如果缓冲区为空,它仍然返回一个空字符串,如果它被部分填充,则返回该部分字符串。 –

+0

为什么当我多次刷新数据流时,ConsoleRead()会返回所有刷新的数据流,即使它们相隔几秒钟,其他时间也会认为它需要继续并返回_without_等待第二次刷新? (在这两种情况下,脚本在冲刷之间的输入都没有发生) – roundar