I am running a tool named "fio" from my java code using process builder.the tool has its source code in C.i need to get values of some variables from the source code of "fio",when i am running the tool in my java code.I tried to search for the solution but could not find any.
how can i do it?can "environment variables" for processbuilder help?
here is the code i am using
String line=null;
ProcessBuilder pb=new ProcessBuilder("fio","inp.fio");
File f=new File("/home/nikhil/Nikhil");
pb.directory(f);
Process p=pb.start();
InputStream i=p.getInputStream();
InputStreamReader ir=new InputStreamReader(i);
BufferedReader bf=new BufferedReader(ir);
InputStream err=p.getErrorStream();
InputStreamReader rerr=new InputStreamReader(err);
BufferedReader bferr=new BufferedReader(rerr);
I'm going to assume you have access to the code for fio and can rebuild it. One mechanism you could use would be to have fio output the local variable state you are interested in to one of the output streams (stdout or stderr) that you are handling, and parse the values out of it as messages whenever it changes and fio outputs an updated value. That keeps the communication fairly simple.
If you have a lot of complex data, you might want to consider creating a separate communication channel (shared memory, for example, or named pipes, or a socket based connection) for shared state. If you are just interested in some cheap debugging, I'd just go with the first approach by outputting something like
DBG{var1}=<value>
to stderr whenever a value of interest changes, and have your stderr stream handler in Java record the state for use wherever you need it.
I can use "shared memory" to share the variable value with another new C program i wrote,now i can call a function from this new C program that will return me the value of the variable which is "shared" in my java code using JNI.
Related
I have just started learning Java with IntelliJ IDE. I know a bit C# so the logic makes some sense, however there is one thing so far I couldn't get over it.
How do I read from the console? In C#, you could easily read what the human typed into it, using Console.ReadLine(). In Java, System.console().readLine(); does not work for me and throws a NullPointerException.
What am I missing here?
NOTE: problem doesn't appear when we run your code from console/terminal via java [options] [MainClass] so if this is valid solution for you you can stop reading here. Rest of this answer is for people who are using some IDEs to run their code.
Problem
Most IDEs are using javaw.exe instead of java.exe to run Java code (see image below).
Difference between these two programs is that javaw runs Java code without association with current terminal/console (which is useful for GUI applications), and since there is no associated console window System.console() returns null. Because of that System.console().readLine() ends up as null.readLine() which throws NullPointerException since null doesn't have readLine() method (nor any method/field).
But just because there is no associated console, it doesn't mean that we can't communicate with javaw process. This process still supports standard input/output/error streams, so IDEs process (and via it also we) can use them via System.in, System.out and System.err.
This way IDEs can have some tab/window and let it simulate console.
For instance when we run code like in Eclipse:
package com.stackoverflow;
public class Demo {
public static void main(String[] args) throws Exception {
System.out.println("hello world");
System.out.println(System.console());
}
}
we will see as result
which shows that despite javaw.exe not having associated console (null at the end) IDE was able to handle data from standard output of the javaw process System.out.println("hello world"); and show hello world.
General solution
To let user pass information to process use standard input stream (System.in). But since in is simple InputStream and Streams are meant to handle binary data it doesn't have methods which would let it easily and properly read data as text (especially if encoding can be involved). That is why Readers and Writers ware added to Java.
So to make life easier and let application read data from user as text you can wrap this stream in one of the Readers like BufferedReader which will let you read entire line with readLine() method. Unfortunately this class doesn't accept Streams but Readers, so we need some kind of adapter which will simulate Reader and be able to translate bytes to text. But that is why InputStreamReader exists.
So code which would let application read data from input stream could look like
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Hello. Please write your name: ");
String name = br.readLine();
System.out.println("Your name is: "+name);
Preferred/simplest solution - Scanner
To avoid this magic involving converting Stream to Reader you can use Scanner class, which is meant to read data as text from Streams and Readers.
This means you can simply use
Scanner scanner = new Scanner(System.in);
//...
String name = scanner.nextLine();
to read data from user (which will be send by console simulated by IDE using standard input stream).
If you realy need to Console object you can compile your class from command line. Firstly in my java file first statement is package com.inputOutput;
Go in your project "src" folder and compile it like : "javac com/inputOutput/Password.java" 'com' and 'inputOutput' are folder(package). Run your class file in src folder
java com.inputOutput.Password". It had worked work for me.
You could use an Jframe.
JFrame frame = new JFrame("titile");
// prompt the user to enter their code
String code = JOptionPane.showInputDialog(frame, "promt here");
java.util.Scanner API is what you are looking for.
I have just started learning Java with IntelliJ IDE. I know a bit C# so the logic makes some sense, however there is one thing so far I couldn't get over it.
How do I read from the console? In C#, you could easily read what the human typed into it, using Console.ReadLine(). In Java, System.console().readLine(); does not work for me and throws a NullPointerException.
What am I missing here?
NOTE: problem doesn't appear when we run your code from console/terminal via java [options] [MainClass] so if this is valid solution for you you can stop reading here. Rest of this answer is for people who are using some IDEs to run their code.
Problem
Most IDEs are using javaw.exe instead of java.exe to run Java code (see image below).
Difference between these two programs is that javaw runs Java code without association with current terminal/console (which is useful for GUI applications), and since there is no associated console window System.console() returns null. Because of that System.console().readLine() ends up as null.readLine() which throws NullPointerException since null doesn't have readLine() method (nor any method/field).
But just because there is no associated console, it doesn't mean that we can't communicate with javaw process. This process still supports standard input/output/error streams, so IDEs process (and via it also we) can use them via System.in, System.out and System.err.
This way IDEs can have some tab/window and let it simulate console.
For instance when we run code like in Eclipse:
package com.stackoverflow;
public class Demo {
public static void main(String[] args) throws Exception {
System.out.println("hello world");
System.out.println(System.console());
}
}
we will see as result
which shows that despite javaw.exe not having associated console (null at the end) IDE was able to handle data from standard output of the javaw process System.out.println("hello world"); and show hello world.
General solution
To let user pass information to process use standard input stream (System.in). But since in is simple InputStream and Streams are meant to handle binary data it doesn't have methods which would let it easily and properly read data as text (especially if encoding can be involved). That is why Readers and Writers ware added to Java.
So to make life easier and let application read data from user as text you can wrap this stream in one of the Readers like BufferedReader which will let you read entire line with readLine() method. Unfortunately this class doesn't accept Streams but Readers, so we need some kind of adapter which will simulate Reader and be able to translate bytes to text. But that is why InputStreamReader exists.
So code which would let application read data from input stream could look like
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Hello. Please write your name: ");
String name = br.readLine();
System.out.println("Your name is: "+name);
Preferred/simplest solution - Scanner
To avoid this magic involving converting Stream to Reader you can use Scanner class, which is meant to read data as text from Streams and Readers.
This means you can simply use
Scanner scanner = new Scanner(System.in);
//...
String name = scanner.nextLine();
to read data from user (which will be send by console simulated by IDE using standard input stream).
If you realy need to Console object you can compile your class from command line. Firstly in my java file first statement is package com.inputOutput;
Go in your project "src" folder and compile it like : "javac com/inputOutput/Password.java" 'com' and 'inputOutput' are folder(package). Run your class file in src folder
java com.inputOutput.Password". It had worked work for me.
You could use an Jframe.
JFrame frame = new JFrame("titile");
// prompt the user to enter their code
String code = JOptionPane.showInputDialog(frame, "promt here");
java.util.Scanner API is what you are looking for.
I know that InputStreams are for reading, and OutputStreams are for writing... but if I have an application that passes all data from an InputStream to the remote side and pushes all received data from that remote side to the OutputStream and I need to send dynamic data to that remote side... how would I enter it into the InputStream? I can do this easily in the Java console since anything entered in is put into System.in and sent to that remote side, and anything coming back is processed through System.out, but obviously I cannot use a Java console in production. How would I emulate this functionality e.g. create a button that sends "command X\r" as if it were typed into the java console?
Note: For background, I'm using JSch to SSH into a Cisco ASA. Where I have set Channel.setInputStream(System.in) and Channel.setOutputStream(System.out) to communicate through console successfully.
I am not familiar with JSch, and I suspect you have this backwards. First, according to their example, you should actually be executing commands with Channel.setCommand(). Then you can use Channel.getInputStream() to obtain a stream that you can read the remote response from.
That aside, a cursory glance at the documentation seems to suggest that you should use the channel's existing streams and read to / write from them, e.g.:
OutputStream out = Channel.getOutputStream();
String str = "command X\r";
out.write(str.getBytes("us-ascii"));
This would make more sense and is much easier to deal with on your end.
However, as to the general question regarding InputStreams: You can use any InputStream as a source for data. It just so happens that System.in is one that comes from standard input (which is essentially a file).
If you want to use data constructed on the fly, you could use a ByteArrayInputStream, e.g.:
String str = "command X\r";
InputStream in = new ByteArrayInputStream(str.getBytes("us-ascii"));
// do stuff with in
You can use any character encoding you want if us-ascii is not appropriate.
But, again, I suspect you are doing this slightly backwards.
I've got a third party program which puts data into a windows named pipe.
I access the pipe with
String pipename = "\\\\.\\pipe\\the_pipe";
RandomAccessFile pipe = new RandomAccessFile(pipename, "r");
DataInputStream input = new DataInputStream(Channels.newInputStream(pipe.getChannel()));
So sometimes someone gets the 'perfect' idea to close the third party program before my small data converting tool which of course closes the pipe. When that happens, my tool writes down the last message received million times into the resultfile and successfully fills every hdd up to the last byte within hours, because I am not able to check if the pipe has been closed.
Things I've tried:
// checking file descriptor and file channel
if(!(pipe.getFD().valid() && pipe.getChannel().isOpen())) {
// quit
}
But both options do not trigger.
Is there a other way to access named pipes where such an information can be obtained?
Or do I have overlooked something?
When that happens, my tool writes down the last message received million times into the resultfile
Only if your tool ignores EOFExceptions and -1 return values from read().
I would recommend looking at JNA to access the named pipe directly. Yes, you can detect the pipe closure if you use JNA.
I have done so in a project called NuProcess available on github.com. Particularly, look at the com.zaxxer.nuprocess.windows package. Look at the WindowsProcess.createPipes() method for setting up pipes (the code creates both ends, you only need one).
On the read side, NuProcess is using Windows IOCompletionPorts for asynchronous I/O (in ProcessCompletions.java), which may be overkill for what you need (or not). But once you get your feet wet setting up the pipes, you should be able to figure it out from there reading the Microsoft API docs.
Alright, I'll get into the meat of things straight away:
I want to run a perl script from a java app (via ProcessBuilder), which will then parse an html page and find out some required information. I then want to pass that information back to my java app, and display that information in a JTextArea.
My knowledge of perl is VERY limited. My original thought was to write this data to a txt file, and then read that file with my java program, which could then display it to JTextArea pretty easily. However, this seems like an ugly solution, compared to simply returning a string.
Please let me know if there is a better way to do this. perhaps a completely different method than what I'm thinking of. Thanks,
Aelfhere
I think you want something like this
You can pass strings between processes only by using some type of inter-process communication: either a pipe or shared memory or using network.
Why can you not do in Java what you want to do in Perl?
when you use a ProcessBuilder you instantiate a Process Object it's java representation of a batch execution
Tipically you can hook process streaming via Java API.
Extracted from Process JAVA API:
abstract
InputStream getErrorStream()
Gets the error stream of the subprocess
abstract
InputStream getInputStream()
Gets the input stream of the subprocess
abstract
OutputStream getOutputStream()
Gets the output stream of the subprocess
If perl script write on standard output stream then you can read that output.
Generally, If process doesn't write on standard output stream then you cannot read it.