我正在使用Windows 7计算机。
我正在开发一个应用程序,它是Haskell的GHCi解释器的前端。用户将输入命令,然后Java将通过运行时的exec()方法执行命令,然后应用程序将显示如果用户刚刚使用命令提示符运行GHCi将显示的文本。
现在,我遇到了打印输出的循环问题。
这是我现在的代码。
public class GHCiTest {
public static Scanner rd, sc;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
System.out.println("Starting... ");
Process p = Runtime.getRuntime().exec("ghci");
PrintStream hugsin = new PrintStream(p.getOutputStream());
InputStream hugsout = p.getInputStream();
sc = new Scanner(hugsout);
rd = new Scanner(System.in);
String rdnextline;
while (true){
while (sc.hasNextLine()){
System.out.println(sc.nextLine());
}
System.out.println("yay");
rdnextline = rd.nextLine();
if (rdnextline == "quit"){break;}
hugsin.println(rdnextline);
hugsin.flush();
}
System.out.println(" ... successful completion.");
}
catch(IOException e) {
e.printStackTrace();
}
}
}
我知道GHCi的初始启动正在运行,因为该程序打印出“GHCi,版本7.10.3:http://www.haskell.org/ghc/ :?求助”。但是,问题似乎是while(sc.hasNextLine())循环,它应该读取命令提示符的输出并输出它直到没有任何东西,因为它不会突破循环并继续读取用户输入。我知道这是因为程序没有打印循环后输入的“yay”标志。
答案 0 :(得分:2)
您的循环不会退出,直到到达流的末尾:
while (sc.hasNextLine()){
System.out.println(sc.nextLine());
}
流的结尾是流程的结束。因此,您的Java程序正在等待子进程运行完成,并终止。一旦发生这种情况,循环将结束,Java程序将向进程发送所需的命令。
抱歉,我的意思是,尝试将所需的命令发送到进程;它不会成功,因为这个过程已经终止。
如果GHCi进程输出"提示"在某种程度上,你可以尝试在那一刻打破你的while(...) { print }
,从用户那里获得输入,将其发送到流程,然后循环返回并重新输入你的while(...) { print }
,等待下一个提示。
假设提示不以换行结束,而是出现在输入用户输入的行的开头,则不能使用while(sc.hasNextLine()) { ... }
类型的循环,因为提示不是完整的行。您可能不得不求助于逐个字符地阅读,在最后一个" n"中寻找提示序列。字符。
看起来您可以更改GHCi中的提示。见here for details。如果您将提示更改为以换行符结尾,则仍可以按行读取流。
while (sc.hasNextLine()){
String line = sc.nextLine();
if (line.equals("YourPromptHere"))
break;
System.out.println(line);
}
(或者,您可以使用线程执行某些操作,以允许两个部分在不相互阻塞的情况下运行。当然,线程会带来自身的问题和复杂性。)
修改强>
我有一个明显的炫目闪光。假设GHC的提示看起来像这样......
GHCi, version 7.10.3 yada, yada, yada ... Main> _
...您可以将扫描仪的分隔符设置为提示字符串Main>
。
// Set scanner delimiter to GHCi's Prompt string
sc = new Scanner(hugsout).setDelimiter("^Main> ");
while (sc.hasNext()) {
// Echo GHCi's output upto the delimiter (prompt)
System.out.println(sc.next());
// Read user input & transfer to GHCi.
System.out.print("Replacement Prompt> ");
rdnextline = rd.nextLine();
if (rdnextline == "quit") {
break;
}
hugsin.println(rdnextline);
hugsin.flush();
}
注意:这没有考虑辅助提示,当GHCi需要更多输入来完成命令时使用。您可以使用匹配任一提示符的"^Main> |\bAlt> "
之类的正则表达式,但是您无法分辨定界符匹配的提示符。
第一个子表达式"^Main> "
匹配一行的开头,后跟" Main> ",其中第二个子表达式"\bAlt> "
仅匹配字边界,后跟" Alt> &#34 ;.这是因为GHCi的输出流看起来像"\nMain> Alt> "
,在Alt>
之前有一段很长的停顿; "换行符" Alt>
之前通常来自输入流上Enter
键的回显。
答案 1 :(得分:2)
在另一个线程中接收ghci的输出。
System.out.println("Starting... ");
Process p = Runtime.getRuntime().exec("ghci");
PrintStream hugsin = new PrintStream(p.getOutputStream());
InputStream hugsout = p.getInputStream();
Scanner rd = new Scanner(System.in);
new Thread(() -> {
try (Reader r = new InputStreamReader(hugsout)) {
int ch;
while ((ch = r.read()) != -1)
System.out.print((char)ch);
} catch (IOException e ) {}
}).start();
Scanner sc = new Scanner(hugsout);
String rdnextline;
while (true) {
rdnextline = rd.nextLine();
hugsin.println(rdnextline);
hugsin.flush();
if (rdnextline.equals("quit")) {
break;
}
}
System.out.println(" ... successful completion.");