所以我的下面的代码片段( concat 方法)主要尝试做两件事:
将该流写入目标WAV文件
public static void concat(ArrayList<String> sourceFiles, String targetFile) {
AudioInputStream targetBuilder = null;
String file;
AudioInputStream nextSource;
for (int i = 0; i < sourceFiles.size(); i++)
{
file = sourceFiles.get(i);
if(targetBuilder == null)
{
targetBuilder = AudioSystem.getAudioInputStream(new File(file));
continue;
}
nextSource = AudioSystem.getAudioInputStream(new File(file));
AudioInputStream appendedFiles = new AudioInputStream(
new SequenceInputStream(targetBuilder, nextSource),
targetBuilder.getFormat(),
targetBuilder.getFrameLength() + nextSource.getFrameLength());
targetBuilder = appendedFiles;
nextSource.close();
}
AudioSystem.write(targetBuilder, AudioFileFormat.Type.WAVE, new File(targetFile));
targetBuilder.close();
}
这个想法借鉴了这个主题:Join two WAV files from Java。现在的问题是连续几次执行这个片段之后,最终会在AudioSystem.write()行上的“stream closed”上抛出IO Exception。堆栈跟踪如下所示:
java.io.IOException: Stream Closed
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:272)
at javax.sound.sampled.AudioInputStream.read(AudioInputStream.java:292)
at java.io.SequenceInputStream.read(SequenceInputStream.java:208)
at java.io.SequenceInputStream.read(SequenceInputStream.java:211)
at javax.sound.sampled.AudioInputStream.read(AudioInputStream.java:292)
at java.io.SequenceInputStream.read(SequenceInputStream.java:208)
at javax.sound.sampled.AudioInputStream.read(AudioInputStream.java:292)
......//with the exact same two lines repeating lots of times
at java.io.SequenceInputStream.read(SequenceInputStream.java:208)
at javax.sound.sampled.AudioInputStream.read(AudioInputStream.java:292)
at com.sun.media.sound.SunFileWriter$NoCloseInputStream.read(SunFileWriter.java:198)
at java.io.SequenceInputStream.read(SequenceInputStream.java:208)
at java.io.InputStream.read(InputStream.java:101)
at com.sun.media.sound.WaveFileWriter.writeWaveFile(WaveFileWriter.java:239)
at com.sun.media.sound.WaveFileWriter.write(WaveFileWriter.java:137)
at javax.sound.sampled.AudioSystem.write(AudioSystem.java:1354)
at com.mycompany.mypackage.AudioUtils.concat(AudioUtils.java:324)
......
所以在我看来,当程序仍然试图从AudioInputStream中读取更多字节到文件时,但在某些时候,流( targetBuilder )只是自行关闭。这对我没有意义,因为我只在我的AudioSystem.write()方法之后关闭了这个流。
现在,如果我真的在for循环中注释这一行:
//nextSource.close();
这个流关闭异常似乎消失了,替换了“FilesNotFoundException:太多的打开文件”,这对我来说很有意义,因为在循环的每次迭代中我都在创建一个新的AudioInputStream并分配对nextSource的引用,但是如果我从不关闭它,最终我用完了打开的文件描述符。
然而我不明白的是,如何关闭此 nextSource 流会以何种方式影响 targetBuilder 流的行为?如果我关闭 nextSource 流,为什么这个流会突然关闭? (我假设两者之间存在联系,如果我错了,请纠正我。)
谢谢!
答案 0 :(得分:0)
SequenceInputStream不会在内存中复制你的流,它只记得链接......这里是读取方法的代码
public int read() throws IOException
{
int ch = -1;
while (in != null && (ch = in.read()) < 0)
{
in.close();
in = getNextStream();
}
return ch;
}
因此,如果您将关闭添加到SequenceInputStream的其中一个流 - 您将获得异常