【问题标题】:Java IO Exception: stream closed when writing from AudioInputStream to a fileJava IO 异常:从 AudioInputStream 写入文件时流关闭
【发布时间】:2023-03-21 03:03:01
【问题描述】:

所以我下面的代码sn-p(concat方法)主要尝试做两件事:

  1. 将从源文件列表中读取的多个 AudioInputStream 连接到一个最终的长流中
  2. 将该流写入目标 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。现在的问题是在连续多次执行这个sn-p之后,最终它会在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 流,为什么该流会突然关闭? (我假设两者之间有联系,如果我错了,请纠正我。

谢谢!

【问题讨论】:

    标签: java audio stream ioexception


    【解决方案1】:

    SequenceInputStream 不会将您的流复制到内存中,它只是记住链接...这是读取方法的代码

    public int read() throws IOException
    {
      int ch = -1;
    
      while (in != null && (ch = in.read()) < 0)
        {
          in.close();
          in = getNextStream();
        }
    
      return ch;
    }
    

    因此,如果您关闭添加到 SequenceInputStream 的流之一 - 您将获得异常

    【讨论】:

    • 谢谢!你的意思是所有的内容都只是作为一些参考放在某个流的地方,只有当它实际上归结为 AudioSystem.write() 时才会被消耗?不过,这并不是每次都会发生。此方法的前几次执行通常会成功。另外,在这种情况下,您会推荐什么作为解决方法?显然我不能让流打开,因为它会达到打开文件描述符的限制,而且我正在连接很多流......
    • 你需要在写入后关闭那些nextSource才能关闭打开的文件。
    • @DiogoSantana 你这是什么意思? nextSource 仅在 for 循环内具有作用域,并且必须在 for 循环完成时进行写入。即使我在写入后关闭它,我也只会关闭 nextSource 引用的最后一个流。我这样做了,它仍然会吐出“打开的文件太多”异常......
    • AudioInputStream 在内部使用 FileInputStream。创建的每个 FileInputStream 都会在操作系统上打开内部文件。所以你需要改变你的代码的逻辑,才能在写完后全部关闭。
    • 尝试将所有内容添加到列表中。然后迭代关闭每个列表。
    猜你喜欢
    • 2014-05-18
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 2017-01-05
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多