I am using jline and I have a neat ConsoleReader and everything works great. However, if you are typing something into the the prompt and there is output on stdout (from another thread), the output splits the word/command that you are typing.
How can I keep the jline prompt at the bottom of the terminal?
I am using jline 1, but I am open to using jline 2 if it is stable enough.
Finally figured this out... here's what you do. First, define these functions:
private ConsoleReader console = ...;
private CursorBuffer stashed;
private void stashLine() {
this.stashed = this.console.getCursorBuffer().copy();
try {
this.console.getOutput().write("\u001b[1G\u001b[K");
this.console.flush();
} catch (IOException e) {
// ignore
}
}
private void unstashLine() {
try {
this.console.resetPromptLine(this.console.getPrompt(),
this.stashed.toString(), this.stashed.cursor);
} catch (IOException e) {
// ignore
}
}
Then when you want to output new data, first invoke stashLine() to save the current console input, then output whatever new lines of output, then invoke unstashLine() to restore it.
Related
I just started using RCP to write Java-based applications. I am trying to add a console view in my app, and output info of log4j to the console. Now it works. But there is a problem, it cannot perform as eclipse witch output once per line, but output all info after the method finish.
Object[] elements = tableViewer.getCheckedElements();
if(elements.length > 0){
for(Object ele : elements){
File file = (File) ele;
logger.info("log4j处理目录" + file.getAbsolutePath());
MessageConsoleStream stream = ConsoleFactory.getConsole().newMessageStream();
stream.println("println处理目录" + file.getAbsolutePath());
try {
stream.flush();
stream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I tried use stream.println() stream.flush(), but it does not work.
It is my first time questing on stackoverflow. Sorry for my english.
Calling Thread.sleep(1000) in the User Interface Thread will block the entire UI and nothing will happen. Never do this.
If you want to do something once a second use the timerExec method of Display to run code.
Something like:
Display.getDefault().timerExec(1000, new Runnable() {
#Override
public void run()
{
// TODO output one item to the log
// TODO if need to run again call
Display.getDefault().timerExec(1000, this);
}
});
The JavaDoc for MessageConsoleStream says:
Clients should avoid writing large amounts of output to this stream in
the UI thread. The console needs to process the output in the UI
thread and if the client hogs the UI thread writing output to the
console, the console will not be able to process the output.
So you must not loop constantly outputting to the stream without letting other code in the UI thread run.
In java, I am trying to read the output from a consoleprogram I wrote in C.
This program is continuously printing its current progress into stdout using printf().
If I run that program in a console, everything is fine, I am seeing the output.
I am now trying to run it from inside java, which also runs fine, the process is starting and calculating, but the whole output however will be read in huge blocks at once (There is no output for some seconds and then everything appears at once).
I assume there is some kind of a buffer in between that must be filled.
In order to draw a progressbar and work with other parameters the program is printing it is neccessary to read from the stdout fluidly and not everything at once.
I already read about this in Questions like Problem reading InputStream from Java Process (Runtime.getRuntime().exec() or ProcessBuilder), but this did not help me very much as I followed the tips in these questions.
Below is the code I am currently trying to use.
public static void main(String[] args)
{
ProcessBuilder builder = new ProcessBuilder("render.exe", "1920", "1080", "10000", "0", "0", "1", "6", "test.png");
try
{
final Process proc = builder.start();
final Thread io = new Thread()
{
#Override
public void run()
{
final InputStream read = proc.getInputStream();
int c;
try
{
while((c = read.read()) != -1)
System.out.print((char)c);
}
catch (IOException e)
{
e.printStackTrace();
}
}
};
io.start();
proc.waitFor();
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
}
The C program probably detects that its stdout is not connected to an interactive console and buffers its output; you cannot change this from Java.
Assuming you use stdio, to make the C program produce output more fluidly you can add fflush(stdout) in appropriate places, or you can disable buffering with a call to setvbuf:
setvbuf(stdout, NULL, _IONBF, 0);
I'd like to know if there's a way where the Java SE allows a passage to be printed out and then in between the line we can allow the user to type the answer on the line.
To be more clear :
Here's an example:
____ reading, Alice also enjoys listening to classical music.
So, when the text is being drawn out using the buffer reader, the user is able to enter the answer on the line itself.
Here's the method of buffer reader:
public void getCloze(){
File file = new File("cloze.txt");
StringBuffer contents = new StringBuffer();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String text = null;
// repeat until all lines is read
while ((text = reader.readLine()) != null) {
contents.append(text)
.append(System.getProperty(
"line.separator"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// show file contents here
System.out.println(contents.toString());
}}
Hope someone can advise me how to and best if there's any tutorial to show the steps.
I dont think it is possible to prompt the user to type in between the already printed line in Java. you have to stop your priniting to take user input and then print further string to the user
It is not entirely clear what your problem is, but you seem to want to know how to write a question or prompt and allow the user to enter the answer on the same line. If so, the "trick" is to use System.out.print(prompt) rather than System.out.println(prompt); i.e. DON'T output a line break after the prompt.
UPDATE - I see what you are asking now.
Well the bad news is that there is no simple way to do that. However, it is doable using something like the charva library or a "curses for Java" library - What's a good Java, curses-like, library for terminal applications?
I'm passing an object to constructor and then adding parameters of this object to HL7.
ORU_R01 is the type of HL7.
When i print HL7 to console, only the last OBX is printed.
What is wrong with my code?
How can i write this HL7 message to socket?
Is there simpler way in java to handel HL7?
public class FlexSMessageHL7 {
private FileWriter writeHL7ToFile;
private PrismaflexSMessage sMessage;
private ORU_R01 message;
private int i = 0;
private OBX obx = null;
public FlexSMessageHL7(FlexSMessage sMessage) {
this.sMessage = sMessage;
this.message = new ORU_R01();
createHL7SMessage();
}
public void createHL7SMessage() {
// Populate the MSH Segment
MSH msh = message.getMSH();
try {
msh.getFieldSeparator().setValue("|");
msh.getEncodingCharacters().setValue("^~\\&");
msh.getDateTimeOfMessage().setValue(sMessage.getTime().toString());
msh.getSendingApplication().getNamespaceID().setValue(String.valueOf(sMessage.getMachID()));
} catch (DataTypeException e) {
e.printStackTrace();
}
// Populate the OBR Segment:time
OBR obr = message.getPATIENT_RESULT().getORDER_OBSERVATION().getOBR();
try {
obr.getObservationDateTime().setValue(String.valueOf(sMessage.getTime()));
} catch (DataTypeException e) {
e.printStackTrace();
}
// Populate the PID Segment:PatientId
PID pid = message.getPATIENT_RESULT().getPATIENT().getPID();
try {
pid.getPatientID().getIDNumber().setValue(sMessage.getPatID());
} catch (HL7Exception e) {
e.printStackTrace();
}
// Populate the OBX Segment:Param_Code, time, Measure_Value
while (i < sMessage.getMsgInfo()) {
for (PrismaflexSRecord sRecord : sMessage.getsRecordCollection()) {
try {
obx = message.getPATIENT_RESULT().getORDER_OBSERVATION().getOBSERVATION(i).getOBX();
obx.getSetIDOBX().setValue(String.valueOf(i));
obx.getObservationIdentifier().getIdentifier().setValue(sRecord.getParamCode());
obx.getDateTimeOfTheObservation().setValue(String.valueOf(sRecord.getTimeStamp()));
obx.getObservationIdentifier().getNameOfCodingSystem().setValue(String.valueOf(sRecord.getMeasureValue()));
i++;
} catch (HL7Exception e) {
e.printStackTrace();
}
}
}
try {
writeHL7ToFile = new FileWriter(File.createTempFile("prismaflexOutputFrom3001HL7", "txt", new File
("c:\\tmp\\prismaflex")));
writeHL7ToFile.write(message.getMSH().toString());
writeHL7ToFile.flush();
} catch (IOException e) {
e.printStackTrace();
}
// Now, Encode the message and look at the output
try {
Parser parser = new PipeParser();
String encodedMessage = parser.encode(message);
System.out.println("Printing HL7 Encoded Message:");
System.out.println(encodedMessage);
} catch (HL7Exception e) {
e.printStackTrace();
}
}
}
As Nicholas Orlowski pointed out, the problem is in the line ending characters, which according to the HL7 standard are CR characters which make a Windows command prompt only reset the cursor to the beggining of the line and overwrite it with next line's content. Therefore for console output You need to replace the line-endings with something else.
For a recent HL7 app using HAPI, which You also seem to be using, I made a little helper method to achieve this function:
private static String replaceNewlines(String input) {
return input.replaceAll("\\r", "\n");
}
The function can be used on all platforms, as it replaces the CR characters with the OS-specific newline character(s).
Then I can use it to output to console as follows:
LOGGER.trace("Generated message contents:\n" + replaceNewlines(outMessage.encode()));
In this case I am using log4j for logging to console, not simple console printout, but the problem was the same for me.
Hope it helps!
Have you considered using the HAPI? It is written for java, it's counter part nHAPI is written for .net as well. Details here:
http://hl7api.sourceforge.net/
I have had a similar problem in my python HL7py library. Many times the console doesn't like printing characters. I had to write a helper that changed CR to LF (line feed) to display the lines correctly. Hope that helps.
It won't display in the console but it will when you write to the file. Try looking at the variable in debug mode and writing it to a file.
I want to run an interactive command with apache commons exec. Everything works except that when my command is executed and waits for user input I don't see my input in the console until I press enter which makes it effectively unusable.
This is an example of an interactive program:
public static void main(String[] args) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while (true) {
System.out.print("=> ");
try {
line = in.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(line);
}
}
Now I want to execute that with apache commons exec like this:
public static void main(String[] args) {
Executor ex = new DefaultExecutor();
ex.setStreamHandler(new PumpStreamHandler(System.out, System.err, System.in));
CommandLine cl = new CommandLine("java");
cl.addArguments("-cp target\\classes foo.bar.Main");
try {
ex.execute(cl);
} catch (ExecuteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
As I said, it basically works, I get the "=>" prompt but when I type something I don't see it until I hit enter. I'm doing this on windows 7 with a cmd prompt.
I'd appreciate any hint on how to achieve the desired behaviour.
Edit: It works as expected on linux. I guess this is an issue with the windows cmd prompt. I'd still like to make this work if at all possible, so I would appreciate any insight into this behaviour on windows.
Edit2: I also tested with msys shell and powershell, both exhibit the same problem.
Edit3: I worked around the issue by launching a seperate cmd prompt. This works, but I still like to understand why.
CommandLine cl = new CommandLine("cmd");
cl.addArguments("/C java -cp target\\classes foo.bar.Main");
thanks
Raoul
I'm not sure exactly what you were expecting to happen here; if the spawned process is designed to wait to read from its input, then it shouldn't be surprising when it does exactly that?
If that's the issue, and your question is "How can I make my program automatically send a newline character to the spawned process' input?", then you'll need to define an OutputStream to write the input to, and get hold of the ExecuteStreamHandler to attach it to the process. Something like the following:
Executor ex = new DefaultExecutor();
// Create an output stream and set it as the process' input
OutputStream out = new ByteArrayOutputStream();
ex.getStreamHandler().setProcessInputStream(out);
...
try
{
ex.execute(cl);
out.write("\n".getBytes()); // TODO use appropriate charset explicitly
...
Using Apache exec org.apache.commons.exec.DefaultExecuteResultHandler you can launch a non-blocking command. And then you can follow the steps #Andrzej mentioned.