I'm experimenting with networking by writing a small chat-room program in Java. Because it's a chat-room, the console is constantly asking for input from the user. My problem is that, after printing a message from another person in the server whilst still asking for input, the console stops showing what I type. Input is still collected, however, so the user can still input messages. There's just no visual feedback. I've tried three different methods of input, BufferedReader (which I'm still currently using), a Scanner, and the system console. They all have the same problem, which leads me to believe it's the windows console. My question is, is it possible to avoid this or is it simply a flaw with the Windows console? Here is my code, with input being the BufferedReader:
// This runs until the console is closed
while(true)
{
// If the user has input something, send it to the server
if(input.ready())
{
String message = input.readLine();
if(!message.equals(""))
{
client.sendString(message);
}
}
// If the server has a message for the client, print it
if(client.input.available() > 0)
{
System.out.println(client.getString());
}
}
Related
I'm trying to make a simple counter that starts between user inputs (3..., 2..., 1..., Go!).
try (var reader = new BufferedReader(new InputStreamReader(System.in))) {
...
try {
for (int i = 0; i < 3; i++) {
System.out.println(i + "...");
Thread.sleep(500);
}
System.out.println("Go!");
} catch (Exception e) {
e.printStackTrace();
}
...
}
The problem is Im still able to press keys between delays, which then gets printed. Is there a way to block BufferedReader while for-each works?
You cannot prevent the user pressing keys while he should be waiting.
For the same reason you cannot prevent your application to receive these characters through System.in up until the BufferedReader. Blocking that is the wrong approach.
What you can do however is ignore those keypresses. But you must prevent that they remain in the input buffer and get evaluated after your loop.
Since you are reading from stdin however, it is not your program to print the characters. I guess it is the terminal emulator that you use when running your console based application. And therefore I am unsure how you can prevent the echo to the console. What undermines my assumption is
https://forums.codeguru.com/showthread.php?466009-Reading-from-stdin-(without-echo)
What proves I am wrong (and what you should try out therefore) is
How to use Scanner to read silently from STDIN in Java?
or more general
https://www.geeksforgeeks.org/ways-to-read-input-from-console-in-java/
Both recommend to suppress the echo by reading from System.console().
Your problem is not related to the BufferedReader, and the solution is probably more complex than what you imagined.
When you run your Java process, it is usually connected to a terminal. This terminal (or emulator) handles your keyboard and usually provides your input line by line to the attached process. The terminal also echos characters as you type. Meaning the Java process does not print the characters you type, you therefor can't prevent them being printed from within the your process.
Terminals and terminal control is highly platform specific. On Linux system you can control the terminal using termios. The flags you want to be disable is ECHO for echoing your keystrokes and ICANON to disable canonical mode so you'd receive input as soon as it is available. You'd have to perform this before your loop. After or in your loop you'd have to consume any input and discard it, enable ECHO and ICANON again. Be aware though that the BufferedReader might have something buffered already and is performing blocking I/O.
termios however is not directly accessible from Java, calls would have to be wrapped through JNI f.i. A quick google search came up with a library called purejavacomm
When I pause the execution in my program with Thread.sleep, it seems that the program is still able to get input, even while it is being paused. Is there any fix to this? I am using Java 2 and I've looked through so many forums, but couldn't find a suitable answer.
This is the code I'm using to pause my program:
Thread.sleep(2000);
int input = c.readInt();
Your program does not control the terminal device. You can see what you type because the software that actually controls the device is reading keyboard input and writing it to the screen. Your program is not getting any input while it's in sleep.
What actually controls the terminal window or device depend on operating system, and things get complicated when dive into the details. For example on Unix, it's handled by a a thing called "line discipline". The default ("canonical") setting lets you edit lines of text before they are sent to your programs. It also intercepts key combinations like control-c and control-z for job control. Further reading: https://en.m.wikipedia.org/wiki/POSIX_terminal_interface
I have a GUI program written in Java which outputs data to the command line using System.out.println. The data is intended to be piped into another program. As an example, I'll pipe the program through head:
$ java MyProgram | head -n10
I want my program to exit when the pipe is broken: in this case, this should happen after MyProgram has printed out ten lines of text.
There is a similar question on this site, and the solution given there works fairly well; for example, I could have the following running in its own thread:
while(!System.out.checkError()) {
// sleep 100ms
}
System.exit(0);
The problem is that PrintStream.checkError() seems to return true only after you have tried to print to the stream and failed. For that reason, my program does not in fact exit until it has printed out eleven lines of text: the pipe is broken after the first ten, but System.out continues to return true until I try to pipe through the eleventh line.
Printing out extra 'junk' lines in order to trigger an error on the PrintStream is out of the question, since the program on the right hand side of the pipe may be very sensitive to the data it receives.
Calling System.out.flush() inside the loop has no effect on PrintStream.checkError(), even though the source code for PrintStream indicates that it ought to call the private ensureOpen method in that class.
How can I reliably test whether System.out is open without printing anything to it?
'Real world' example: suppose that I have some program consumer that takes in command line input and does something with it. Certain pieces of input will call consumer to fail silently. Since the input to consumer is sometimes long and abstruse, I write a GUI program InputProvider in Java where I can click buttons and have the corresponding commands printed out to stdout. If I pipe the output of InputProvider into consumer, then I am able to control consumer graphically.
Unfortunately, there seems to be no way for InputProvider to notify the user when consumer has shut down, except by attempting to write to consumer and getting an exception of some kind.
I don't think you can fix this in Java. There's nothing wrong with System.out until you write to it and it fails. Another process (head) ended but the Java process can't know about that.
So I think that you have two options.
don't use pipe to head but limit the output in your Java code - then you'll know when to stop
accept that the last line will fail and handle the exception appropriately
Try to set a new stream for the system that way you'll be able to check if that stream is closed or not: OutputStream output = new FileOutputStream("c:\\data\\system.out.txt"); and PrintStream printOut = new PrintStream(output);. Then set it here: System.setOut(printOut); and inside the if you can check if(printOut.checkError())
My problem is kind of strange. I have made a program in Java which fetches some information from a website, writes it to a file and prints it out in the console. It works fine when I start it but after a several passes it stops printing the information out while it continues to write them to the file. I have observed this behavior and figured out that it occurs totally randomly.
It is pretty large and has 15 classes so I don't think it's useful to completely paste it here but I'll make a pattern:
while(true) {
InfoStoringClass isc = new InfoStoringClass(getInformation());
printToFile(isc);
System.out.println(isc.toString());
}
I am creating a GUI using Java. This GUI launches a program from the command line using the ProcessBuilder class.
A little information on the process being launched: from the command line, it creates another window and prints information to said window.
In my GUI window, I have a text area to where I would like to redirect said output. I originally intended to use a SwingWorker object to constantly check for more output and not hold up the GUI. To test and make sure I had the original syntax down (without even bringing the GUI into things) I thought I would print the output from the secondary process' window to System.out. However, something seems to be wrong as I can see the output in the secondary process' window, but not the terminal from which I am working.
Excerpt of code is as follows:
Process p = pb.start();
Scanner s = new Scanner(p.getInputStream());
SwingWorker pipe = new SwingWorker<String, Void> (){
public String doInBackground(){
while(run){
if(s.hasNextLine()){
System.out.println("S has next!");
System.out.println(s.nextLine());
}
}
return null;
}
};
pipe.execute();
The boolean run is defined elsewhere in the program and is set to false when the process p exits or is force quit (additional question: is that a really bad idea? I feel like it might be...).
Does anyone have an idea as to why I am never getting any output when I see it being printed to the other window? Initially my reaction was to use p.getOutputStream() but Scanner does not take an outputStream as a paramter.
Thank you for your time.
You should also scan p.getErrorStream() - some programs write to STDERR which is indistinguishable from STDOUT when run from the command line. It is generally good practice to consume both streams, as if either one is not consumed it can cause the external process to hang.
If the external process is writing its output to its own window, it is almost certain that the output is NOT being written to STDOUT, which is what you are reading with your code. If it did so, then the external program's output would be appearing both in its window and in the command line session from which it was launched (if one existed). Without access to the source of the external program it's unlikely you will be able to intercept its output unless the authors made provisions for that functionality (i.e. a command-line switch that redirects output to STDOUT instead of the window).
As to p.getOutputStream(), that returns a stream which is "output" from YOUR point of view -- i.e. you write to it to send data to the process' STDIN. Your use of p.getInputStream() would be correct for the case where the external program writes to its STDOUT.