我正在尝试按照Mkyong的说明通过Java代码调用shell命令。我的代码是:
public class ExecuteShellCommand {
public static void main(){
String absolutePath = "/home/marievi/Downloads/small.mp4";
String command = "ffmpeg -i " + absolutePath;
ExecuteShellCommand obj = new ExecuteShellCommand();
String output = obj.executeCommand(command);
System.out.println(output);
}
public String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
但是我得到一个空输出,只打印一个换行符。但是,当我使用Mkyong的示例运行代码时:
public static void main(){
ExecuteShellCommand obj = new ExecuteShellCommand();
String domainName = "google.com";
String command = "ping -c 3 " + domainName;
String output = obj.executeCommand(command);
System.out.println(output);
}
输出输出。什么出了什么问题?当我直接执行命令时:
ffmpeg -i /home/marievi/Downloads/small.mp4
从命令行,我得到了所需的输出:
ffmpeg version 3.3.4-1~14.04.york1 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
configuration: --prefix=/usr --extra-version='1~14.04.york1' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-libmodplug --enable-libopus --enable-libpulse --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
libavutil 55. 58.100 / 55. 58.100
libavcodec 57. 89.100 / 57. 89.100
libavformat 57. 71.100 / 57. 71.100
libavdevice 57. 6.100 / 57. 6.100
libavfilter 6. 82.100 / 6. 82.100
libavresample 3. 5. 0 / 3. 5. 0
libswscale 4. 6.100 / 4. 6.100
libswresample 2. 7.100 / 2. 7.100
libpostproc 54. 5.100 / 54. 5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/maxez/Downloads/small.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42isomavc1
creation_time : 2010-03-20T21:29:11.000000Z
encoder : HandBrake 0.9.4 2009112300
Duration: 00:00:05.57, start: 0.000000, bitrate: 551 kb/s
Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 560x320, 465 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
Metadata:
creation_time : 2010-03-20T21:29:11.000000Z
encoder : JVT/AVC Coding
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 83 kb/s (default)
Metadata:
creation_time : 2010-03-20T21:29:11.000000Z
答案 0 :(得分:2)
帮自己一个忙,避免依赖mkyong.com。该网站只是反刍您可以在公共文档中轻松找到的内容,而不考虑其建议有多糟糕或陈旧,或者信息的过时程度如何。
事实上,Runtime.exec在过去的十三年已经过时了。它的替代品,在Java 5中引入,是ProcessBuilder。通过使用ProcessBuilder,您可以允许外部进程的错误输出显示在与Java程序的错误输出相同的位置。目前,你没有在任何地方展示它,所以没有办法知道出了什么问题。
同样,StringBuffer已经过时且非常陈旧;它的替代品是StringBuilder。它们是相同的,除了StringBuffer具有线程安全的额外开销,这很少有用。
此外,waitFor()
等待进程结束。显然,在阅读过程输出之前,不应该调用它。在阅读完所有输出行后调用它。
最后,异常意味着“操作没有成功,你不应该继续,就好像它成功了。”如果你得到一个例外,你的进程没有成功。自从读取输出这个过程对你要做的事情至关重要,继续下去是没有意义的。而是将任何捕获的异常包装在未经检查的异常中,例如RuntimeException。 (更好的选择是完全删除try / catch,并将这些异常类型添加到executeCommand和main方法的throws
子句中。)
public static void main() {
String absolutePath = "/home/marievi/Downloads/small.mp4";
String[] command = { "ffmpeg", "-i", absolutePath };
ExecuteShellCommand obj = new ExecuteShellCommand();
String output = obj.executeCommand(command);
System.out.println(output);
}
public String executeCommand(String[] command) {
StringBuilder output = new StringBuilder();
try {
ProcessBuilder builder = new ProcessBuilder(command);
// Share standard input/output/error descriptors with Java process...
builder.inheritIO();
// ... except standard output, so we can read it with getInputStream().
builder.redirectOutput(ProcessBuilder.Redirect.PIPE);
Process p = builder.start();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
}
p.waitFor();
} catch (IOException | InterruptedException e) {
// Process failed; do not attempt to continue!
throw new RuntimeException(e);
}
return output.toString();
}
答案 1 :(得分:1)
您的代码没有任何问题。 只有ffmpeg写入stderr而不是stdout。
你可以通过用getErrorStream()替换getInputStream()来使它工作。