I'm using proc_open in php to call java application, send a large text to it for processing and capture a returned result. Is it possible to pass several text strings (input streams) instead of just one?
This is what I've got at the moment:
fwrite($pipes[0], $input);
fclose($pipes[0]);
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
If I do something like this, java still recognizes it as one input stream:
fwrite($pipes[0], $input);
fwrite($pipes[0], $input1);
fwrite($pipes[0], $input2);
fclose($pipes[0]);
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
So is something like this possible at all? If not, any alternatives? I can't use command line params because it's a large text with multiple lines.
It depends what you are trying to do, and what the java application expects.
If you want the Java application to see the concatenation of $input, $input2 and $input3, then sure ... your code will do that.
If you want the Java to be able to automatically see those inputs as distinct streams, then no. As far as the Java IO system is concerned, the bytes are just bytes. There are no natural boundaries ... apart from the ultimate end of the (combined) stream.
If you want the Java to see one stream that it can then split into three streams, then it is possible, but it will require some programming effort.
On the PHP side, you have to add some kind of "framing" information to the stream that tells the Java side where one "stream" ends and the next one starts.
On the Java side, you have to look for / interpret that framing information.
The framing could be done by sending a byte count for each stream followed by the bytes, or it could be done with marker characters or sequences that designate the end of a stream.
Nope, a process has only a single standard input stream, as well as a single standard output stream and a single standard error (output) stream (this is true for every process not just java or php).
You can set up some socket communication, e.g. a client-server architecture, that would allow for multiple streams, but would only help if both client (php) and server (java) can do multi threading.
You can send through the pipe some delimiter sequence, so java can distinguish the three input strings
You can simply use more than one proc_open
EDIT:
You can use files instead of the stdin and stdout (php and java could share those)
You can use unix pipes (similar to the socket solution), but this is pretty hard to implement.
Related
I want to store a bunch of protobuf messages in a file, and read them later.
In java, I can just use 'writeDelimitedTo' and 'parseDelimitedFrom' to read and write to a file. However, I want to read it in Python, which only seems to have a 'ParseFromString' method.
Some SO questions are very similar, such as, Parsing Protocol Buffers, written in Java and read in Python, but that is only for a single message: not for multiple.
From the proto guide it is written that you need to deal yourself with the size of your message:
Streaming Multiple Messages
If you want to write multiple messages to a single file or stream, it
is up to you to keep track of where one message ends and the next
begins. The Protocol Buffer wire format is not self-delimiting, so
protocol buffer parsers cannot determine where a message ends on their
own. The easiest way to solve this problem is to write the size of
each message before you write the message itself. When you read the
messages back in, you read the size, then read the bytes into a
separate buffer, then parse from that buffer. (If you want to avoid
copying bytes to a separate buffer, check out the CodedInputStream
class (in both C++ and Java) which can be told to limit reads to a
certain number of bytes.)
https://developers.google.com/protocol-buffers/docs/techniques
A simple solution could be for you to serialize each proto in base64, on a new line in your file.
Doing so, it would be pretty easy on python to parse and use them.
For a while, I've been working on a Java client that sends level information to save online. I have managed using printwriter, but it is really inefficient, and a simple 300KB level turns out to be 3MB after the transfer, and is rather slow.
I know people have used "file_get_contents("php://input")", such as in receive output from java DataOutputStream in a php page, but I am not sure how to receive specific data from:
//phpsend is the DataOutputStream using POST (java)
phpsend.writeUTF(username);
phpsend.writeUTF(verificationId);
phpsend.writeInt(levelsize);
phpsend.write(level); //level has been converted to a byte array
how would I read each separate write? I know Java had DataInputStream, which had all the corresponding read functions, but how would I do that in PHP? I've heard of "Sockets" and "SOAPClient", but I could not find any information that I could use
So I have found that
file_get_contents("php://input")
seems to do the what I want. Simply assign its result to a variable
$data = file_get_contents("php://input");
and the $data get all Java sent.
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.
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.
Here's my scenario. I have an application written in C++ but not the complete source but the "meat" of it is there. I also have a compiled exe of this application. It communicates to a server somewhere here on our network. I am trying to replicate the C++ code in java, however it uses dwords and memory references, sizeof etc, all things that don't exist in java since it manages it's own memory. It builds this large complex message and then fires it over the network. So I am basically sniffing the traffic and inspecting the packet and trying to hardcode the data it's sending over to see if I can get a response from the server this way. However I can't seem to replicate the message perfectly. Some of it, such as the license code it sends is in "clear hex", that is, hex that translates into ascii, where-as some other portions of the data are not "clear hex" such as "aa" which does not translate into ascii (or at least a common character set?? if that makes any sense I'm not sure).
Ideally I'd like to not do it like this, but it's a stepping stone to see if can get the server to respond to me. One of the functions is for the application to register itself and that's the one I am trying to replicate.
Some of my assumptions above may be wrong, so I apologize in advance. Thanks for your time.
In Java, all "character" data is encoded as Unicode (and not ASCII). So when you talk to something outside, you need to map the internal strings to the outside world. There are several ways to do it:
Use a ByteArrayOutputStream. This is basically a growing buffer of bytes to which you can append. This allows you to build the message using bytes.
Use getBytes(encoding) where encoding is the encoding the other side understands. In your case, that would be "ASCII" for the text parts.
In your case, you probably need both. Create a byte buffer and then append strings and bytes to it and then send the final result (getByteArray()) via the socket API.