在java中执行外部命令行实用程序并将其打包到runnable jar

时间:2017-11-29 21:40:02

标签: java eclipse command-line jar executable-jar

我正在尝试构建一个使用sox命令行实用程序将.dat文件转换为.wav文件的程序。

我的方法是创建一个.bat脚本并运行它。这在eclipse中有效但是当它在可执行jar文件中导出和打包时它会失败。这可能是由于两个问题所致。

第一个可能是从jar文件中访问sox.exe甚至是我自己的目录。

另一个是打包sox12181文件夹,其中包含sox需要运行的文件以及jar文件中的sox.exe本身。我已经搜索了如何打包它,并且只找到了在资源中打包图像的示例。

这是我的代码:

package executableIII;

import java.awt.Desktop;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.Queue;

public class SoundManipulation {

    public static void main(String[] args) throws IOException {
        Queue<Double> queue1 = new LinkedList<>();
        Queue<Double> queue2 = new LinkedList<>();
        StringBuilder sb = new StringBuilder();
        double sampleRate = 44100;
        int m = (int) (sampleRate * 3);
        int n = 700;
        for (int i = 0; i < n; i++) {
            queue1.add((Math.random() * 2) - 1);
        }
        queue2.add(0.0);
        for (int i = 0; i < m; i++) {
            double a = queue1.remove();
            double b = queue2.remove();
            double c = 0.99 * (a + b) / 2;
            queue1.add(c);
            queue2.add(a);
            sb.append(i * (1 / sampleRate) + " " + c + "\n");
        }
        FileOutputStream fs = new FileOutputStream(System.getProperty("user.dir") + "\\sox12181\\generated.dat");
        OutputStreamWriter out = new OutputStreamWriter(fs);
        out.write("; Sample Rate 44100\n; Channels 1\n");
        out.write(sb.toString());
        out.close();
        fs.close();
        try {
            FileOutputStream fsExec = new FileOutputStream("converter.bat");
            OutputStreamWriter outExec = new OutputStreamWriter(fsExec);
            outExec.write("cd " + System.getProperty("user.dir") + "\\sox12181\nsox generated.dat generated.wav");
            outExec.close();
            fsExec.close();
        } catch (IOException e) {
            System.err.println(e);
        }
        File temp1 = new File("converter.bat");
        Desktop.getDesktop().open(temp1);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        File temp2 = new File("sox12181\\generated.wav");
        Desktop.getDesktop().open(temp2);
    }
}

以下是我程序中路径的屏幕截图:

https://imgur.com/a/Is4Zb

我是stackoverflow平台的新手,所以如果有什么我应该改变的话请指出来。 谢谢!

1 个答案:

答案 0 :(得分:1)

基于@zingerella和@howlger讨论我做了一些测试然后没有,不可能在jar中执行可执行文件,无论如何我做了一个解决方法,你可以看到它在docs工作。基本上它会将可执行文件复制到 SO 临时文件夹然后执行它。我的项目正在使用gradle,你也可以这样做this link,以下片段会认为你的可执行文件将在jar根结构中

final InputStream in = Main.class.getResourceAsStream("/myprogram");
if (in == null) {
    throw new RuntimeException("program not found");
}

final File tmpProgram = Files.createTempFile("mypgrogram", ".tmp").toFile();
Files.copy(in, tmpProgram.toPath(), StandardCopyOption.REPLACE_EXISTING);
tmpProgram.deleteOnExit();
tmpProgram.setExecutable(true);

final Process p = Runtime.getRuntime().exec(tmpProgram.getAbsolutePath());
System.out.println(p.waitFor());

for (int c; (c = p.getInputStream().read()) != -1; ) {
    System.out.print((char) c);
}
System.out.println();

for (int c; (c = p.getErrorStream().read()) != -1; ) {
    System.out.print((char) c);
}
System.out.println();