3

我正在尝试使用 Linux 下的 ProcessBuilder 类将 mp3 文件解码为 wav 文件。由于某种原因,该过程不会停止,因此我必须手动取消它。

有人可以给我一个提示。我认为引用的代码很容易重现:

import java.io.*;

public class Test {
 public static void main(String[] args) {
     try {
         Process lameProcess = new ProcessBuilder("lame", "--decode", "test.mp3", "-").start();
         InputStream is = lameProcess.getInputStream();
         FileOutputStream fileOutput = new FileOutputStream("test.wav");
         DataOutputStream dataOutput = new DataOutputStream(fileOutput);


         byte[] buf = new byte[32 * 1024];
         int nRead = 0;
         int counter = 0;
         while((nRead = is.read(buf)) != -1) {
             dataOutput.write(buf, 0, buf.length);
         }

         is.close();
         fileOutput.close();

     }
     catch (Exception e) {
         e.printStackTrace();
     }
 }
}

jstack的输出

"main" prio=10 tid=0x0000000002588800 nid=0x247a runnable [0x00007f17e2761000]
   java.lang.Thread.State: RUNNABLE
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(FileInputStream.java:236)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
    - locked <0x00000000eb5b1660> (a java.io.BufferedInputStream)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at Test.main(Test.java:17)
4

2 回答 2

9

您需要排空进程的输出(通过getInputStream())和错误(通过getErrorStream())流,否则可能会阻塞。

引用流程文档

由于部分原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至死锁。

(适用于错误和输出流)

您可能需要在不同的线程中耗尽每个流,因为每个流在没有数据时可能会阻塞。

于 2011-09-26T22:55:46.580 回答
3

使用像LAMEOnJ这样的 LAME Java 包装器可能会容易得多。这样您就可以避免产生进程,并且您可以与 lame 进行交互,就好像它是一个 Java 库一样。

于 2011-09-26T23:03:57.573 回答