Pass Value between Java and C - java

I have a Java GUI and a C program. C program calculates given value(args). I want to call C calculator in Java, and change label to returned value in GUI (label changes almost every second).
I thought some ways,
Socket programming (probably not efficient in same computer)
File operations (Java writes input, c calculates then java reads calculated value)
JNICALL stuff, but i dont know how to get value from c file.
SharedMemory (i have no idea about windows shm)
What is the best way to solve this problem?

You could take a look at JNA, if your C program is a DLL with export functions.
Remember from a past project it works very nicely, without having to do the JNI bits yourself.

I had to do something similar at my job, I wrote a helper program in C++ to access some custom made database and my main application was in Java. The database API was only available to C++ programs.
What I did was to start the C++ process from Java and communicate via command line args and stdout.
List<String> cmdPathAndArgs = Arrays.asList("/path/to/binary", "--arg1", "--arg2");
ProcessBuilder pb = new ProcessBuilder(cmdPathAndArgs);
Processpp = pb.start();
InputStream stream = pp.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
InputStream errorStream = pp.getErrorStream();
BufferedReader errorBr = new BufferedReader(new InputStreamReader(errorStream));
If your progran generates output in both stdout and stderr you may get into a deadlock. You should empty both streams regularly.

If you can build your C code into a shared library, then JNI is probably your best bet. Sockets will be more than fast enough to handle 1 update a second. Using files will probably be slower than sockets. Shared memory is fine too, however I think sockets is probably a simpler interface for what you want to do.

Related

Java write to Stdin

So I have imported a jruby interpreter as a library to run an external ruby application. However I need to interact with the ruby application in some way. Right now I have the ruby application outputting information on stdout and requesting user options in stdin.
So if I want java to be able to handle inserting the options instead of a user, I'll need a way that I can write to the stdin somehow from java to choose the options. Does anyone know how I can do this? Or even a better way to do this?
I'm calling jruby like so:
String[] newargs = new String[2];
newargs[0] = "-S";
newargs[1] = "path_to_some_rubyfile.rb"
org.jruby.Main jruby = new org.jruby.Main();
ruby.main(newargs);
The ruby app outputs stuff like this:
How do you feel today?
(1) Happy
(2) Sad
And then waits for the user input to enter 1 or 2.
But I would like Java to input these options instead of having a user do it.
I am not overly familiar with JRuby, I honestly would have thought that it automatically wraps System.in. Check to see that such an option does exist. Otherwise my personal choice would be to simply start a new Process("ruby") and use the streams provided by that.
Regards
md_5
Jruby does have a way to contruct it by specifying an inputstream and two output streams, however what I found to work better was to create a PipedOutPutstream that writes to a PipedInputStream and you set the System input to the PipedInputStream like so:
PipedOutputStream inwriter = new PipedOutputStream();
PipedInputStream input = new PipedInputStream(inwriter);
System.setIn(input);
inwriter.write("1\n".getBytes());

Reading Random Access File with Buffered Reader

i am trying to read a huge file ( > 1GB) , i am thinking that reading it as a random access file with a buffered reader would be efficient.
i need to read the file line by line and parse it
However being new to JAVA IO Api , i'm not sure how can i do this..
i appreciate your help.
You can use Java's BufferedReader for this:
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
// Do some stuff with the line
}
fileName is the path to the file you want to read.
Do you need to read all of it and from the beginning? You can use a RandomAccessFile to jump to different parts of the file if you know what byte you can start at. I think it is the seek function that does this.
While it is perfectly doable in java, I wanted to suggest based on my experience:
If you're on Unix platform, you may use external shell script for searching through the GBs of log. sed is very optimum for this purpose. Specific usage here: http://www.grymoire.com/Unix/Sed.html
Call shell script through java file whenever you need to read/grep through the log file.
How?
1) In your java code, use ProcessBuilder class. It can take shell script as arg to constructor
ProcessBuilder obj = new ProcessBuilder("FastLogRead.sh");
2) Create object for Process
Process process = obj.start();
3) You can read the output of this shell, directly in your BufferedRead through this
BufferedReader br=new BufferedReader(new InputStreamReader(process.getInputStream()));
Pros:
Speeds up execution by avg. 10 times (I searched through around 4GB log file)
Cons:
Some developers don't like bringing in light-weight shell script in realms of java, hence want to go for java's RandomAccessFile. This is justified.
For your case, you may choose between standardization and performance.

How to avoid loading a large file repeatedly?

I'm trying to call a Java program (Stanford Chinese Word Segmenter) from within python. The Java program needs to load a large (100M) dictionary file (word list to assist segmentation) which takes 12+ seconds. I was wondering if it is possible to speed up the loading process, and more importantly, how to avoid loading it repeatedly when I need to call the python script multiple times?
Here's the relevant part of the code:
op = subprocess.Popen(['java',
'-mx2g',
'-cp',
'seg.jar',
'edu.stanford.nlp.ie.crf.CRFClassifier',
'-sighanCorporaDict',
'data',
'-testFile',
filename,
'-inputEncoding',
'utf-8',
'-sighanPostProcessing',
'true',
'ctb',
'-loadClassifier',
**'./data/ctb.gz',**
'-serDictionary',
'./data/dict-chris6.ser.gz',
'0'],
stdout = subprocess.PIPE,
stdin = subprocess.PIPE,
stderr = subprocess.STDOUT,
)
In the above code, './data/ctb.gz' is the place where the large word list file is loaded. I think this might be related to process, but I don't know much about it.
You might be able to use an OS specific solution here. Most modern Operating Systems have the ability to have a partition in memory. For example, in Linux you could do
mkfs -q /dev/ram1 8192
mkdir -p /ramcache
mount /dev/ram1 /ramcache
Moving the file to that directory would greatly speed I/O
There might be many ways to speed up the loading of the word list, but it depends on the details. If IO (disk read speed) is the bottleneck, then a simple way might be to zip the file and use a ZipInputStream to read it - but you would need to benchmark this.
To avoid multiple loading, you probably need to keep the Java process running, and communicate with it from Python via files or sockets, to send it commands, rather than actually launching the Java process each time from Python.
However, both of these require modifying the Java code.
If the java program produces output as soon as it receives input from filename named pipe and you can't change the java program then you could keep your Python script running instead and communicate with it via files/sockets as #DNA suggested for the Java process (the same idea but the Python program keeps running).
# ...
os.mkfifo(filename)
p = Popen([..., filename, ...], stdout=PIPE)
with open(filename, 'w') as f:
while True:
indata = read_input() # read text to segment from files/sockets, etc
f.write(indata)
# read response from java process
outdata = p.stdout.readline()# you need to figure out when to stop reading
write_output(outdata) # write response via files/sockets, etc
You can run a single instance of the JVM and use named pipes to allow the python script to communicate with the JVM. This will work assuming that the program executed by the JVM is stateless and responds on its stdout (and stderr perhaps) to requests arriving via its stdin.
Why not track whether the file has already been read on the python side? I'm not a python whiz, but I'm sure you could have some list or map/dictionary of all the files that have been opened so far.

(Java) File redirection (both ways) within Runtime.exec?

I want to execute this command:
/ceplinux_work3/myName/opt/myCompany/ourProduct/bin/EXECUTE_THIS -p cepamd64linux.myCompany.com:19021/ws1/project_name < /ceplinux_work3/myName/stressting/Publisher/uploadable/00000.bin >> /ceplinux_work3/myName/stressting/Publisher/stats/ws1.project_name.19021/2011-07-22T12-45-20_PID-2237/out.up
But it doesn't work because EXECUTE_THIS requires an input file via redirect, and simply passing this command to Runtime.exec doesn't work.
Side note: I searched all over on how to solve this before coming here to ask. There are many questions/articles on the web regarding Runtime.exec and Input/Output redirect. However, I cannot find any that deal with passing a file to a command and outputting the result to another file. Plus, I am totally unfamiliar with Input/Output streams, so I have a hard time putting all the info out there together for my specific situation.
That said, any help is much appreciated.
P.S. If there are multiple ways to do this, I prefer whatever is fastest in terms of throughput.
Edit: As discussed in my last question, I CANNOT change this to a bash call because the program must wait for this process to finish before proceeding.
Unless you are sending a file name to the standard input of the process, there is no distinction of whether the data came from a file or from any other data source.
You need to write to the OutputStream given by Process.getOutputStream(). The data you write to it you can read in from a file using a FileInputStream.
Putting that together might look something like this:
Process proc = Runtime.getRuntime().exec("...");
OutputStream standardInputOfChildProcess = proc.getOutputStream();
InputStream dataFromFile = new FileInputStream("theFileWithTheData.dat");
byte[] buff = new byte[1024];
for ( int count = -1; (count = dataFromFile.read(buff)) != -1; ) {
standardInputOfChildProcess.write(buff, 0, count);
}
I've left out a lot of details, this is just to get the gist of it. You'll want to safely close things, might want to consider buffering and you need to worry about the pitfalls of Runtime.exec().
Edit
Writing the output to a file is similar. Obtain a FileOutputStream pointing to the output file and write the data you read from Process.getInputStream() to that OutputStream. The major caveat here is that you must do this operation in a second thread, since accessing two blocking streams from the same thread will lead to deadlock (see the article above).

Building an irc client in Java

I'm trying to write an ircBot in Java for some practice. I am using this sample code as the base. I'm trying to figure out how to get it to read in text from my console so I can actually talk to people with the bot.
There's the one while loop that takes in the input from the ircserver and spits it out to console and responds to PINGs. I'm assuming I have to have another thread that takes the input from the user and then uses the same BufferedWriter to spit it out to the ircserver again but I can't get that figured out.
Any help would be awesome!
In the code you have linked to, the 'reader' and 'writer' instances, are indeed connected to respectively the ingoing and outgoing ends of the two-way socket you have established with the IRC server.
So in order to get input from the User, you do indeed new another thread which takes commands from the user in some fashion and acts upon these. The most basic model, would naturally be to use System.in for this, preferably wrapping it so that you can retrieve whole line inputs from the User, and parse these as a command.
To read whole lines from System.in you could do something like this:
BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = bin.readLine()) != null) {
// Do stuff
}
You could also consider using one of the CLI libraries that is out there for Java, like JLine
If you really want to do yourself a favour, I recommend (after having used it extensively) switching to pircbot. Pircbot really is a wonderful library and will let you get an IRC bot up and running in just a few minutes. Check out some of the examples on the site, it's super easy to use.

Categories

Resources