J'ai posté la même question ici il y a quelques jours (Java reading standard output from an external program using inputstream), et j'ai trouvé d'excellents conseils pour traiter un bloc en cours de lecture (while (is.read())! = -1)), mais je n'arrive toujours pas à résoudre le problème.Java IO entréestream bloque en lisant la sortie standard et l'erreur standard d'un programme externe C
Après avoir lu les réponses à cette question similaire,
Java InputStream blocking read (esp, la réponse Posté par Guss),
Je commence à croire que le bouclage d'un flux d'entrée en utilisant is.read() La condition! = -1 ne fonctionne pas si le programme est interactif (c'est-à-dire qu'il prend plusieurs entrées de l'utilisateur et présente des sorties supplémentaires sur les entrées suivantes, et le programme ne sort que lorsqu'une commande de sortie explicite est donnée). J'avoue que je ne connais pas grand-chose du multithread, mais je pense que j'ai besoin d'un mécanisme pour suspendre rapidement les threads du flux d'entrée (un pour stdout, stderr) quand une entrée utilisateur est nécessaire, et reprendre une fois l'entrée fourni pour empêcher un blocage. Ce qui suit est mon code actuel qui connaît un bloc sur la ligne indiquée:
EGMProcess egm = new EGMProcess(new String[]{directory + "/egm", "-o", "CasinoA", "-v", "VendorA", "-s", "localhost:8080/gls/MessageRobot.action ", "-E", "glss_env_cert.pem", "-S", "glss_sig_cert.pem", "-C", "glsc_sig_cert.pem", "-d", "config", "-L", "config/log.txt", "-H", "GLSA-SampleHost"}, new String[]{"PATH=${PATH}"}, directory);egm.execute(); BufferedReader stdout = new BufferedReader(new InputStreamReader(egm.getInputStream())); BufferedReader stderr = new BufferedReader(new InputStreamReader(egm.getErrorStream())); EGMStreamGobbler stdoutprocessor = new EGMStreamGobbler(stdout, egm); EGMStreamGobbler stderrprocessor = new EGMStreamGobbler(stderr, egm); BufferedWriter stdin = new BufferedWriter(new OutputStreamWriter(egm.getOutputStream())); stderrprocessor.run(); //<-- the block occurs here! stdoutprocessor.run(); //EGM/Agent test cases //check bootstrap menu if(!checkSimpleResult("******** EGM Bootstrap Menu **********", egm)) { String stdoutdump = egm.getStdOut(); egm.cleanup(); throw new Exception("can't find '******** EGM Bootstrap Menu **********'" + "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump); } //select bootstrap stdin.write("1".toCharArray()); stdin.flush(); if(!checkSimpleResult("Enter port to receive msgs pushed from server ('0' for no push support)", egm)){ String stdoutdump = egm.getStdOut(); egm.cleanup(); throw new Exception("can't find 'Enter port to receive msgs pushed from server ('0' for no push support)'" + "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump); }
...
public class EGMStreamGobbler implements Runnable{
private BufferedReader instream; private EGMProcess egm; public EGMStreamGobbler(BufferedReader isr, EGMProcess aEGM) { instream = isr; egm = aEGM; } public void run() { try{ int c; while((c = instream.read()) != 1) { egm.processStdOutStream((char)c); } } catch(IOException e) { e.printStackTrace(); } }
}
Je présente mes excuses pour la longueur du code, mais mon les questions sont,
1) Y a-t-il un moyen de contrôler le processus de prise en intrants (stdout, stderr) sans utiliser read()? Ou est-ce que je ne fais qu'appliquer cela mal? 2) Le multithreading est-il la bonne stratégie pour développer le processus de saisie des flux d'entrée et d'écriture d'une sortie? PS: si quelqu'un peut fournir un problème similaire avec la solution, cela m'aidera beaucoup!