1

I'm trying to build a program that uses the sox command line utility to convert a .dat file to a .wav file.

My approach was to create a .bat script and run it. This works in eclipse but when exporting and packaging it in an executable jar file it fails. This is probably due to two problems.

The first would probably be accessing the sox.exe and even my own directory from inside the jar file.

The other would be packaging the sox12181 folder which includes the files sox needs to run and sox.exe itself inside the jar file. I've searched for how to package it and only found examples packaging images inside resources.

Here's my code:

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

Here's a screenshot of the paths in my program:

https://imgur.com/a/Is4Zb

I'm new to the stackoverflow platform so if there's anything I should change please do point it out. Thank you!

Zingerella
  • 450
  • 2
  • 11
  • So the sox12181 folder is not packaging inside the jar when you generate it in eclipse? – deFreitas Nov 29 '17 at 22:31
  • no, this is a user resource packaging problem. My main concern is if even if i was able to package it, how can i make command prompt access the sox.exe command line utility and execute the "sox generated.dat generated.wav" command – Zingerella Nov 29 '17 at 22:44
  • 2
    I did some tests then no, is not possible to execute a executable inside a jar, anyway I did a workaround for that you can see it working [at this link](https://github.com/mageddo/execute-binary/blob/master/src/main/java/com/mageddo/Main.java). Basically it will copy the executable to the system a temp folder then execute it. My project is using gradle anyway you can do it using eclipse as well at the same way – deFreitas Nov 30 '17 at 02:55
  • 2
    What @deFreitas says, but using [`File#createTempFile(...)`](https://docs.oracle.com/javase/9/docs/api/java/io/File.html#createTempFile-java.lang.String-java.lang.String-). – howlger Nov 30 '17 at 08:29
  • @deFreitas Thank you!! It works if I create a temp file as howlger suggested – Zingerella Nov 30 '17 at 13:21
  • @howlger Your comment was on point, helped out alot thanks! (If you guys could post an answer I can flag as answered [ or do i answer it myself?] ) – Zingerella Nov 30 '17 at 13:22
  • https://stackoverflow.com/questions/25635636/eclipse-exported-runnable-jar-not-showing-images I used this link to know how to package my sox.exe program into the jar file then edited the code @deFreitas used for accessing it a bit to make it work Thank you guys :) – Zingerella Nov 30 '17 at 13:24
  • Good, I can post the answer, I didn't it before because I wasn't sure if it would help you. – deFreitas Nov 30 '17 at 13:39

1 Answers1

1

Based on @zingerella and @howlger discussion I did some tests then no, is not possible to execute a executable inside a jar, anyway I did a workaround for that, you can see it working at this link. Basically it will copy the executable to a SO temp folder then execute it. My project is using gradle anyway you can do it using eclipse as well, the follow snippet will consider that your executable will be in the jar root structure

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();
deFreitas
  • 4,196
  • 2
  • 33
  • 43