Is there a way to make command text follow input? - java

Say i want to print a text prompt in java, and then get input from user from System.in. But another thread can write to System.out and "takes down" the input but the text prompt stays up, which is normal.
Enter input here ->
<waiting for input ...>
But if a thread writes something the following occurs:
Enter input here ->
...
...
...
Thread output here
...
...
<Waits for input here>
Is there any trick to "bind" the input with the prompt text?

You could wrap your system.outs into a logging class, and when you want to print something add it to a queue in the new logging class.
When ever you ask for user input, have it activate a lock in the logging class so anything in the queue doesn't get printed until the user input is submitted, then have all the output in the queue get printed.
This will result in all the output text being paused while input is coming in. It won't interrupt your input, so the input will be bound around the cursor, but you also won't get any output. Up to you if that's worth it.

Is there any trick to "bind" the input with the prompt text?
Nope. It's your code; it's up to you to cooperate with yourself. That could mean building (or finding a library which provides) a wrapper API around System.(in|out) so you don't have to worry about accidentally causing this issue. But no, there is no magical silver bullet.

I am not sure if any existing implementations exist but this task should be simple enough.
Make a class e.g SyncConsole which synchronizes your prints and reads.
Basically have only SyncConsole singleton in your code that writes and reads to the io streams of the console.
Then your program can do something like
SyncConsole.readInput("Text to display");
SyncConsole.print("Text");
These calls can then be properly synchronized to suit your needs. E.g if some code requested input, buffer requests to print till the input has been received and so forth.
If you are familiar with concurrency in java this should be fairly simple to build and will give you the desired behaviour.

import java.util.LinkedList;
import java.util.Queue;
public class MainDemo {
public void queueExample() {
Queue queue = new LinkedList();
queue.add("Java");
queue.add("DotNet");
queue.offer("PHP");
queue.offer("HTML");
System.out.println("remove: " + queue.remove());
System.out.println("element: " + queue.element());
System.out.println("poll: " + queue.poll());
System.out.println("peek: " + queue.peek());
}
public static void main(String[] args) {
new MainDemo().queueExample();
}
}

Related

Why my code in java does not output the message "you have broken the rule" even if I inputed the number out of the given range?

I am using the if else statement to output the message Exelent or you have broken the rule based on the user input. However, why my code always output the Excelent! although I have written the number out of the given range?
The code:
import java.util.Scanner;
public class numberOfChoice{
public static void main(String[] args) {
int choosenNumber;
Scanner input=new Scanner (System.in);
System.out.println("Write your number in between 1 and 100");
choosenNumber=input.nextInt();
if (choosenNumber>0 && choosenNumber<100) {
System.out.println("Excelent!");
} else{
System.out.println("You have broken the rule");
}
}
}
I would like to add the output as a picture but I could not upload it.
Honestly I'm unable to replicate this problem. When I copy paste this code and run it, it runs as expected. Try running it in another compiler and see what happens
I'm not sure why your code doesn't work, but I would suggest running the code in another IDE (you can find a few online, try this one: https://www.onlinegdb.com/online_java_compiler, it's pretty good).
Maybe double-check to see if you are running the wrong program (although very unlikely), and make sure what you input is correct. Also check to see if the code is the same - especially in the if-else statement, make sure it's && (and) and not || (or).

Networked GUI handler for binary protocol

Alright, so I created a Client and Server that manipulates a Map via a GUI interface using a text based protocol. The handler below was used to create a "work order" to manipulate the GUI on a separate thread from the network communications.
class RemoteInputHandler implements Runnable,SharedVariables
{
#Override
public void run()
{
try
{
String input = netComm.reader.readLine();
while (input != null)
{
// Make a separate copy of the input string
String inputCopy = input;
// Post a work order to process the command on the GUI thread
Platform.runLater(() ->
{
handleRemote(inputCopy);
});
// Get the next remote input
input = netComm.reader.readLine();
}
} catch (IOException ex)
{
throw new RuntimeException(ex);
}
}
This pulls the next line of input from the server without freezing up the GUI. I then use the input in the handleRemote() method with a scanner to determine what is done with the input. The string retrieved from the reader looked something like "put key value". I'd then get the first word "put", using a scanner, to get the "command" and use a switch statement to determine how the GUI / Map should be updated on the client and server side respectively.
I'm doing another GUI based program that uses a binary protocol instead, but I'm having trouble figuring out how to handle the information in the same way as I did with the readLine() above. Is there a way to do this? Am i thinking about it the wrong way? I thought I could just get all of the bytes into an array, but I'm having trouble even figuring that out.
I could really use a hint! Thank you!

How do I replace typed text in a console when something is printed there?

I am reading and writing from console created by running my application from a batch file.
I am creating a small servlet and I am running into the problem that while I am typing, things are printed (such as things like clients connecting or disconnecting) on the end of where I am typing. It basically makes everything look funny and I have been trying to find a way to copy what I was typing, print out what occurred (ie. Client x connects!) in its place and paste the command I was typing below so that I can continue.
I think I got a part of it working (the part where what I was typing is replaced), but I cannot think of a way to copy what I was typing or put it on the next line so that I can continue typing to it.
This method is called whenever anything is to be printed out, it basically puts the time stamp on the output.
public void say(String s){
Calendar calendar = Calendar.getInstance();
Date now = calendar.getTime();
Timestamp current = new Timestamp(now.getTime());
SimpleDateFormat date = new SimpleDateFormat("HH:mm:ss");
String time = date.format(current);
//how it gets printed
System.out.println("\r" + time + "> " + s);
}
The thread I am using to wait for input:
Thread thread = new Thread(){
public void run(){
Scanner scan = new Scanner(System.in);
while(scan.hasNextLine()){
String s = scan.nextLine();
//do something with s?
}
}
};
thread.start();
Any help would be greatly appreciated!
Maybe in the say method, before it prints anything out, it can check the io buffer or pipeline to see whether it has something (ex: new command you are typing) in it. If so, save it, do what you gotta do, and put it back in the buffer.

Intercepting and parsing Logger or console output without disturbing it

I am having some trouble with Java. What I want is pretty simple,
I am developing a plugin for a mod of a well-known game, Minecraft, and I need to be able to parse every line of console output that comes through to STOUT.
I've looked around on the internet but I can't seem to find anything I can use to do this. I know that some console output is through the default Logger, and some is through system.out. I have a function, parseConsole(String line) that will parse the line and do something if it contains a word, etc etc. I want this function to be called for every line of output displayed on the console, but it must not interrupt the flow, as in every line will still be sent to the console after being parsed by my function.
you can use System.setOut() to replace the console PrintStream. you can replace this with an implementation which inspects the text on its way to the console.
here is an example of how you might filter:
public class MyFilterPrintStream extends PrintStream {
#Override public void print(String s) {
// ... process output string here ...
// pass along to actual console output
super.print(s);
}
}
// install my filter
System.setOut(new MyFilterPrintStream(System.out));

Removing access to System.out in java

I maintain an application which acts as a container for multiple individual programs. These programs have their own dedicated logging facility, i.e. everything they log does to a special log file.
Nevertheless, application developers seem to love to throw System.out.println and e.printStackTrace calls all over, making it impossible to maintain a clean console when running the container.
How can I prevent these applications from polluting System.out and System.err?
Implementation notes:
the applications use Log4j for logging;
the container also uses the console for logging, but it is strictly reserved for lifecycle events and problems, so I still need the console;
the applications are loaded using a custom classloader, but no security checks are applied.
Update:
Simply redirecting System.out would not work since it redirects all output, so something like this fails:
System.setOut(new PrintStream(new OutputStream() {
#Override
public void write(int b) {
throw new Error("Not on my watch you don't");
}
}));
Logger logger = Logger.getLogger(Runner.class);
logger.info("My log message");
This should succeed.
Update 2:
The applications are loaded and configured using code similar to
App app = new UrlClassLoader(...).loadClass(className)).newInstance();
app.setLogger(loggerForClass(app));
Log4j is loaded from the system class loader.
Assuming that you can control your containers output you can do the following:
import java.io.*;
public class SysOut {
public static void main(String[] args) throws Exception {
PrintStream pw = new PrintStream(new FileOutputStream("a.txt"));
PrintStream realout = System.out;
System.setOut(pw);
System.out.println("junk");
realout.print("useful");
}
}
$ java SysOut
useful
$ cat a.txt
junk
You can use System.setOut() and System.setErr() to redirect stdout and stderr to instances of PrintStream.
While Java defines a standard System.out and System.err, these can be overwritten with your own streams. See http://www.devx.com/tips/Tip/5616
Basically you can set up new streams that either pipe to the logging, or simply let data flop off into nothingness. My preference would be the latter, as it would instantly cure developers from relying on System.out and err as anything they write there just disappears.
**Update:
I just reread your stipulations in the question and see you still need the console for the container application. This might still work if you write a wrapper around the standard stream so you can check each call and see if it is coming from the parent application (and pass it on) or a child application (and block it)
Use aversion therapy. A visit from "The Inspectors" is scheduled whenever any code is checked in containing unpleasant constructs.
Nice cubicle you got ere, be shame if anyfing appened to it.
If you have a headless build mechanism, ant or such like then you could add CheckStyle to the build and configure checkstyle to fail the build if it finds any System.out.println or e.printStackTrace in the code.
If you don't have a headless build I would recommend that you build one as it means you have repeatable, predictable builds.
System.setOut will redirect all output - but the PrintStream you supply can decide how the output is handled. Thus I'm sure you could provide such a stream that would only actually print statements from your application.
The only tricky part really is being able to detect what's a valid call and what's not. A working, but likely very slow way to do this, would be to call Thread.currentThread().getStackTrace() and see what code (or package, at least) is calling you (simply returning if it's not a valid one). I wouldn't recommend this though as the performance hit would be staggering, especially doing this on every byte read.
A better idea might be to set a ThreadLocal flag in all of your valid, container threads. Then you can implement the PrintStream something like the following:
public class ThreadValidity extends ThreadLocal<Boolean>
{
private static final INSTANCE = new ThreadValidity();
#Override Boolean initialValue() { return false; }
public static ThreadValidity getInstance() { return INSTANCE; }
}
class VerifyingPrintStream extends PrintStream
{
private boolean isValidThread()
{
return ThreadValidity.instance().get();
}
public void println(String s)
{
if (!isValidThread()) return;
super.println(s);
}
public void println(Object o)
{
if (!isValidThread()) return;
super.println(o);
}
// etc
}
Alternatively, if you're able to change the printlns in the container code, things get easier. You can hand off all the console writes to a specific worker; and have this worker "steal" System.out (store it in its own field and use it directly for writing output) while setting the actual System.out to a no-op writer.
The key here is to configure log4j before redirecting the output streams, e.g.
BasicConfigurator.configure();
System.setOut(...);
System.setErr(...);
System.out.println("I fail");
Logger.getLogger(...).info("I work");
Convert the System.out and System.err streams to special implementations that throw a RuntimeException("Use logging instead of System.out") every time a character is written.
If your container is important, they will get the idea pretty quickly :)
(For extra bonus throw OutOfMemoryException instead ;-))
What I have done is redirect the PrintStream for System.out and System.err to commons-logging as INFO and ERROR level logging respectively.
This gets trickier if you want some threads to be able to write to the console or you want logs to go to the console as well but it can be done.
You can actually get and store System.out/err before replacing them.
OutputStream out=System.getOut(); // I think the names are right
System.setOut(some predefined output stream, null won't work);
out.println("Hey, this still goes to the output");
System.out.println("Oh noes, this does not");
I've used this to intercept all the System.out.println's in the codebase and prefix each line of output with the method name/line number it came from.
Close the System.out and System.err streams.
We use the log4j trick but log to separate files (stdout.log, stderr.log). It's not useful to have their output mixed in with the parts that actually understand logging...

Categories

Resources