[Java] Benutzeroberfläche für NeroAacEnc.exe

(AM)(D)evil

Fleet Captain Special
Mitglied seit
11.10.2007
Beiträge
293
Renomée
1
Standort
Oberbayern
Hi Leute,

vorab: ich hab schon gegoogelt aber keine Lösung für mein Problem gefunden.

Also zur Problembeschreibung:

Ich wollte mir mit Hilfe von Java eine GUI für den neroAacEnc.exe (Nero AAC Encoder) basteln. Die Gui steht soweit, nur habe ich ein Problem mit dem exec(String) Befehl, der ja ein Singleton erzeugen soll indem ein externer Prozess ausgeführt werden soll.
Nun ein Ausschnitt vom Quelltext:

String exe = "C:\\NeroAACcodec\\win32\\neroAacEnc.exe";
String option = "-cbr";
String value = "64000";
String inputf = "C:/Users/(AM)(D)evil/Music/0001_Eng-Gru.wav";
String outputf = "C:/Users/(AM)(D)evil/Music/0001_Eng-Gru.m4a";
String command = "cmd /c "+exe+" "+option+" "+value+" -if "+inputf+" -of "+outputf;
Runtime.getRuntime().exec(command);

Nach ein wenig rumprobiererei habe ich festgestellt dass im command String das führende "cmd /c" weggelassen werden kann, aber das nur am rande.

Wenn ich diesen Code nun ausführe wird neroAacEnc.exe im Taskmanager für ein paar Sekunden mit 50% CPU-Auslastung angezeigt und fällt dann gleich wieder auf 0% runter.
In diesem kurzen Zeitfenster wird die Ausgabedatei "outputf" erzeugt, aber nur mit einer Größe von ca. 700 kb. Diese Datei lässt sich auch nicht mit dem WMP abspielen.

Nach weiterem Beobachten habe ich mal spaßeshalber sämtliche "javaw.exe" im Taskmanager geschlossen und siehe da, Nero beendet seinen Job und konvertiert die Datei ohne weitere Probleme.

Nur ist das ein Problem weil ich so keine Stapelverarbeitung realisieren kann -.-

Hatte hier schon einmal jemand ein ähnliches Problem mit dem exec() Befehl?

Ach ja, der ProcessBuilder als Alternative zu exec(); macht keinen Mucks...

Ich hoffe ich habe das Problem ausreichend beschrieben.

Gruß (AM)(D)evil
 
Zuletzt bearbeitet:
Ich vermute ein Problem mit den Streams.

Will das Programm eine Eingabe (also in den InputStream)? Oder muss dieser Stream evtl. explizit geschlossen werden?

Wird Kommandozeilenausgabe ausgegeben?
Falls ja, solltest du diese aus dem Output- und/oder ErrorStream holen (oder die Streams schließen, das sollte auch gehen). Ich habe schon einen ähnlichen Fall beobachtet, der darauf schließen ließ, dass diese Ausgaben in einen internen Puffer wandern. Ist dieser Puffer voll, bleibt das Programm stehen.
 
Ich habe jetzt mal sämtliche Streams vom Prozess geschlossen und siehe da - du hattest recht. Jetzt muss ich nur noch kontrollieren ob alle streams den Fehler hervorrufen oder ob evtl. nur einer dafür verantwortlich ist.

Zu deiner Frage: Ja der Encoder gibt auf der Kommandozeile den Fortschritt aus, sprich die Anzahl der Sekunden die bereits enkodiert wurden.

EDIT: anscheinend reicht es den ErrorStream zu schließen.
EDIT2: Vielen Dank für deine schnelle Antwort ThePsycho
 
Zuletzt bearbeitet:
Ok, jetzt ist das eine Problem gelöst und neue Fragen kommen auf ;) Ich schreib hier einfach mal und google im Anschluss - man will sich ja mitteilein xD.

Ich hab mit das jetzt so vorgestellt dass ich diese GUI für den NeroAACEncoder mit einer Warteschlange versehe und eine Option einfüge die den Benutzer entscheiden lässt wie viele Instantzen von der Encoder.exe gleichzeitig laufen dürfen.

Um das zu realisieren muss man ja von den Prozessen irgendwie auslesen wie weit sie sind. Im Fall der Benutzung des Encoders per Kommandozeile gibt er aus wie viele Sekunden bereits enkodiert wurden. Das wollte ich dann nutzen um den Fortschritt der einzelnen Threads zu scannen um einen neuen Thread anzustoßen wenn ein alter beendet wurde. Nur komm ich nicht dahinter wie ich das auslesen kann.

Normalerweise wird doch der in der Kommandozeile ausgegebene Text per "getInputStream()" ausgegeben oder?
Habe mir das mit einer verschachtelten Zeile so vorgestellt:
BufferedReader br = new BufferedReader(new InputStreamReader(Process.getInputStream()));
while(true){
System.out.println(br.readLine());
}
leider kommt als Output nur "null null null null..." -.-

und das auch wieder erst nachdem der separate Thread beendet wurde. Ich dachte wenn ich das in einen eigenständigen Thread auslagere werden die Zeilen zeitgleich ausgegeben, falsch gedacht ;).
 
Du hast ja schon oben geschrieben:
Es reicht aus, den ErrorStream zu schließen. Demnach müsste auch die Ausgabe, die du suchst, über den ErrorStream gehen.
Und bitte nicht "while(true)" - ich hoffe das war nur n kurzer Test.
 
ja war nur ein Test ;)
Hat es dir weh getan sowas zu lesen?
Output vom Errorstream:
* *
* Copyright 2009 Nero AG *
* *
* Package version: 1.5.4.0 *
* See -help for a complete list of available parameters. *
*************************************************************
Processed 0 seconds...
Processed 2 seconds...
Processed 4 seconds...
Processed 6 seconds...

sodala jetzt kann es weitergehen :-)

Eine Frage am Rande, wie lange programmierst du schon Java @ ThePsycho?
 
Zuletzt bearbeitet:
Das ist nicht so leicht zu beantworten.
Java war die Hauptsprache im Studium, aber da waren natürlich noch ein paar andere. Und reines Programmieren gibts im Studium nur wenig.
In der Arbeitswelt bin ich seit knappen 5 Jahren, dort hab ich ca. 50 % mit Java gemacht.

Also pures Java schätze ich so 3,5 Jahre, Informatik/IT allgemein seit 9 Jahren. :)
 
Probiers mal mit

Code:
Process p = Runtime.getRuntime().exec(command);
InputStream inStream = p.getErrorStream();
		    
int b;

String response = "";
		            
while((b = inStream.read()) != -1) {
         response += (char)b;
}

System.out.println(response);

p.waitFor();

Das ganze natürlich in nem try-catch block.


€dith:
hrrm vergesst es, irgendwie hab ich dezent ignoriert, dass das problem scheinbar gelöst wurde. is schon wieder viel zu spät am abend :(
 
Zuletzt bearbeitet:
Nichts desto trotzt vielen Dank für deine Anteilnahme an meinem Problem :-)
 
Hat jemand von euch schon Erfahrung im Umgang mit dem ProcessBuilder gesammelt?
Eigentlich müsste es doch möglich sein diesen mit dem gleichen String wie es mit Runtime.exec() möglich war zu starten - oder liege ich da falsch?

Wenn ich das versuche spuckt er mit immer error=2 "Die Datei konnte nicht gefunden werden" aus :(

Edit:

Den Error bringt er nur wenn ich den ProcessBuilder(String)-Konstruktor verwende und dort die ganzen Parameter in einen String einfüge wie beim Runtime().exec...
Mit ProcessBuilder(List<String>) funktioniert es schon weiter, bis auf ein paar kleine Details die ich noch austüfteln muss^^.

Edit2:

Jetzt nimmt das Ganze schon langsam eine akzeptable Form an. Die Befehle werden in eine Warteschlange abgelegt die dann per Knopfdruck abgearbeitet wird. Auf wunsch des Benutzers mit einem, zwei oder maximal x(= Anzahl der Kerne) parallel Arbeitenden Instanzen von neroAacEnc.exe :-) Ist eine echte Zeitersparnis wenn man nen Haufen WAVs hat und die umwandeln möchte... im vergleich zum gehacke auf der Konsole ;)

greets AMDevil
 
Zuletzt bearbeitet:
Zurück
Oben Unten