Reputation: 572
I need to do some numerical calculations in my java application. For several reasons I decided to use Octave for that purpose.
I tried to write a simple interface myself. Since Octave can be used via command line I wanted to do this simply by starting a Process via ProcessBuilder and write/read to it using streams.
Starting a windwos terminal and interacting with it works fine (with commands like cd, dir, etc). When I started octave that way, everything seemed to work fine, but after some tests i found two problems:
When I produce an error, in my java application the streams close and i can't interact any further instead of just getting the message and move on like in octave itself.
I can write to those streams almost as if I was using octave via command line directly, but when i want to create a function, i allways get "warning: function name 'someFunction' does not agree with function filename '' ", although I'm not using a function script file. In Octave it works.
Here is my test-code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
public class CLPI {
public static void main(String[] args) {
String func = "function a = func(b)" + System.lineSeparator()
+ "a = b;" + System.lineSeparator()
+ "endfunction" + System.lineSeparator();
ProcessBuilder builder = new ProcessBuilder(pathToOctaveCliExe,"--silent","--no-window-system");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
Process p = builder.start();
String s;
setUpProcessStreamThreads(p, System.out, System.err);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream ()));
writer.write(func);
writer.newLine();
writer.flush();
while((s = br.readLine()).compareToIgnoreCase("exit")!=0)
{
writer.write(s);
writer.newLine();
writer.flush();
}
writer.write("quit");
writer.newLine();
writer.flush();
p.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Closing program!");
}
public static void setUpProcessStreamThreads(final Process p, final PrintStream ops,PrintStream eps)
{
final InputStreamReader osr = new InputStreamReader(p.getInputStream());
final InputStreamReader esr = new InputStreamReader(p.getErrorStream());
Thread outputThread = new Thread(new Runnable() {
public void run() {
BufferedReader br = new BufferedReader(osr);
String line = null;
try {
while ((line = br.readLine()) != null) {
ops.println("pos: " + line);
}
System.out.println("End of OutputStream!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
Thread errorThread = new Thread(new Runnable() {
public void run() {
BufferedReader br = new BufferedReader(esr);
String line = null;
try {
while ((line = br.readLine()) != null) {
eps.println("pes: " + line);
}
System.out.println("End of ErrorStream!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
outputThread.setDaemon(true);
errorThread.setDaemon(true);
outputThread.start();
errorThread.start();
}
}
Does someone know what causes these problems and how to fix them?
Best regards
Thorsen
ps: Before trying to write my own I looked for an existing interface and found one that should be suitable, called javaoctave (https://kenai.com/projects/javaoctave/pages/Home). On a virtual Ubuntu it worked, but on my system (Windows 10) it blocks when I try to use OctaveEngine's put method (to send a variable from java to octave), without any error message or warning. In debug mode I get "error: load: failed to load matrix constant", which is probably caused by using the debug mode, so it doesn't give any further (relevant) information.
Alternatively to my own interface, if someone knows how to make this old one work again that would be fine for me, too.
Upvotes: 3
Views: 3167
Reputation: 572
I totally forgot about this as I was busy. I solved it myself and got a working beta version for an interface. You can find it here. You will see that it's incomplete and not very well documented, but it's pretty easy to use and give all basic functionality (reading and writing variables, calling functions).
If you use this keep in mind that data exchange between octave and java uses the standard text streams and therefor might be slow for big matrices and many read/write operations. This is also due to the data being read/written (by default) in its ieee hex representation(-> binary exchange using string characters), but it prevents rounding errors. Just keep your data in octave as much as possible.
I hope this will be helpfull. Feel free to use this, just make your improvements etc accessable for others as well.
Upvotes: 1