使用来自 Java 的 Octave

Using Octave from Java

我需要在我的 java 应用程序中进行一些数值计算。出于几个原因,我决定为此目的使用 Octave。

我试着自己写了一个简单的界面。由于 Octave 可以通过命令行使用,我想通过 ProcessBuilder 启动一个进程并使用流 write/read 来简单地做到这一点。

启动 windwos 终端并与其交互工作正常(使用 cd、dir 等命令)。当我以这种方式开始八度时,一切似乎都很好,但经过一些测试后我发现了两个问题:

  1. 当我产生错误时,在我的 java 应用程序中,流关闭并且我无法进行任何进一步的交互,而不仅仅是获取消息并像八度本身一样继续前进。

  2. 我几乎可以像直接通过命令行使用 Octave 一样写入这些流,但是当我想创建一个函数时,我总是得到 "warning: function name 'someFunction' does not agree with function filename '' ",尽管我不使用函数脚本文件。在 Octave 中有效。

这是我的测试代码:

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();
    }
}

有人知道导致这些问题的原因以及如何解决这些问题吗?

此致

索尔森

ps:在尝试编写自己的接口之前,我查找了一个现有的接口并找到了一个应该合适的接口,称为 javaoctave (https://kenai.com/projects/javaoctave/pages/Home)。在虚拟 Ubuntu 上它有效,但在我的系统 (Windows 10) 上,当我尝试使用 OctaveEngine 的 put 方法(将变量从 java 发送到 Octave)时它会阻塞,没有任何错误信息或警告。在调试模式下,我得到 "error: load: failed to load matrix constant",这可能是使用调试模式引起的,因此它没有提供任何进一步的(相关)信息。

或者我自己的界面,如果有人知道如何让这个旧界面再次工作,那对我来说也很好。

忙的时候完全忘记了这件事。我自己解决了它并获得了一个界面的工作测试版。你可以找到它 here。您会发现它不完整且没有很好的文档记录,但它非常易于使用并提供所有基本功能(读取和写入变量、调用函数)。

如果您使用它,请记住八度和 java 之间的数据交换使用标准文本流,因此对于大矩阵和许多 read/write 操作来说可能很慢。这也是由于数据在其 ieee 十六进制表示中为 read/written(默认情况下)(-> 使用字符串字符的二进制交换),但它可以防止舍入错误。尽可能将数据保持在八度范围内。

希望对您有所帮助。请随意使用它,让其他人也可以访问您的改进等。