I have built a game of text based BlackJack and am coding a bot to play the game and record the results. I have successfully launched the game and read the initial data from the console however once the bot decides his move I cannot either write that into the Blackjack console or retrieve the response that the game provides.
Here is the code so far:
public static void main(String[] args) {
try {
ProcessBuilder builder = new ProcessBuilder("java","app.App");
builder.directory(new File("C:\\Users\\damon\\OneDrive\\school\\code\\BlackJack"));
builder.redirectErrorStream(true);
Process process = builder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
String line1 = reader.readLine(); // Player's total
String line2 = reader.readLine(); // Player's cards
String line3 = reader.readLine(); // Can split
String line4 = reader.readLine(); // Dealer's total
String line5 = reader.readLine(); // Dealer's cards
// Process the lines to extract and store the data
int playersTotal = Integer.parseInt(line1);
String[] playerCards = line2.split(" ");
boolean canSplit = line3.equals("s");
int dealersTotal = Integer.parseInt(line4);
String[] dealerCards = line5.split(" ");
Stratergy strat=new Stratergy(playersTotal, playerCards[0], canSplit,dealersTotal);
writer.write(strat.suggestAction()+"\n");
System.out.println(line1+"\n"+line2+"\n"+line3+"\n"+line4+"\n"+line5+"\n"+strat.suggestAction());
System.out.println(reader.readLine());
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
As the word 'buffer' suggests,
BufferedWriterbuffers.That means
someBufferedWriter.write("Hello!")does absolutely nothing at all. It just.. shoves "Hello!" in the buffer. It's purely a memory operation. Not a thing happens to the underlying stream.That's the point - many raw OS level resources have the property that interacting with them is expensive, and, tends to work not so much as a continuous stream of data, but instead as a sequence of blocks which are reconstituted back into a continuous stream on the other side. With the obvious conclusion that sending things 1 byte at a time is incredibly inefficient (as in, thousands of times slower) vs just sending data in full blocks.
That's why it works that way - if you need that buffering thing, use it. If you don't, then don't. Or, if you somehow insist on using
BufferedWriterhere, theflush()call tells BW to send its buffer now. So, add that. Right after your.writecall, immediately callflush(). Until you do (or until the BW object decides its buffer is full enough to fire off a block, which just that little command string definitely isn't going to fill up), that java process you are starting receives no data whatsoever.Note that instead of PB you can just re-assign sysin and sysout (
System.setIn/System.setOut) and then callapp.App.main(args)yourself. Saves a JVM invocation, and is probably a lot simpler than futzing about with ProcessBuilder here. But, once you add that flush(), things will work fine. Or if they still don't, the communications channel between the 2 processes is no longer the problem.