Java声音API在播放音频文件后将其锁定
我正在尝试使用Javax.sound来播放.wav文件。 一切正常,文件按预期播放,最后我关闭剪辑并关闭音频输入流。但是,在此之后,该文件仍处于锁定状态(正在使用中),我无法触摸它而不出现异常:java.nio.file.FileSystemException:alerting.wav:该进程无法访问该文件,因为另一个进程正在使用它 代码示例如下:Java声音API在播放音频文件后将其锁定,java,audio,javasound,Java,Audio,Javasound,我正在尝试使用Javax.sound来播放.wav文件。 一切正常,文件按预期播放,最后我关闭剪辑并关闭音频输入流。但是,在此之后,该文件仍处于锁定状态(正在使用中),我无法触摸它而不出现异常:java.nio.file.FileSystemException:alerting.wav:该进程无法访问该文件,因为另一个进程正在使用它 代码示例如下: static private class SoundThread extends Thread implements LineListener {
static private class SoundThread extends Thread implements LineListener {
private boolean playCompleted;
private int cycles;
public SoundThread(int repeats) {
cycles = repeats;
}
@Override
public void run() {
Clip clip;
AudioInputStream inputStream;
File soundFile = new File("alerting.wav");
try {
inputStream = AudioSystem.getAudioInputStream(soundFile);
try {
clip = AudioSystem.getClip();
clip.addLineListener(this);
clip.open(inputStream);
while(cycles > 0) {
playCompleted = false;
clip.setFramePosition(0);
clip.start();
while(!playCompleted) {
Thread.sleep(1000);
}
Thread.sleep(audioRepeatTime * 1000);
cycles--;
}
//clip.drain();
clip.close();
inputStream.close();
System.out.println("All closed");
try {
this.finalize();
} catch (Throwable ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (Exception ex) {
Main.syslog(Level.WARNING, "E1001 could not play alert sound", ex);
} finally {
inputStream.close();
}
} catch (UnsupportedAudioFileException ex) {
Main.syslog(Level.WARNING, "E1001 could not play alert sound", ex);
} catch (IOException ex) {
Main.syslog(Level.WARNING, "E1001 could not play alert sound", ex);
}
}
@Override
public void update(LineEvent event) {
LineEvent.Type type = event.getType();
System.out.println("Event: " + type);
if(type == LineEvent.Type.STOP) {
playCompleted = true;
} else if (type == LineEvent.Type.CLOSE) {
System.out.println("listener closed");
}
}
}
public static void PlayAlertSound() {
if(enableAudio) {
SoundThread st = new SoundThread(audioLoops);
st.start();
}
}
public static void PlayAlertSound(int repeats) {
if(enableAudio) {
SoundThread st = new SoundThread(repeats);
st.start();
}
}
在Java线程列表中,我看到“Java声音事件调度器”正在运行。我想这就是文件被锁定的原因。
你知道我该怎么解决这个问题吗?感谢API提供的剪辑状态: 请注意,某些行一旦关闭,就无法重新打开。试图 重新打开此行将始终导致
LineUnavailableException
我将提出一些额外的建议
加载音频资源的更好方法是使用class.getResource
方法,而不是使用File
。此方法返回一个URL
,然后可以将其作为参数传递给AudioSystem.getAudioInputStream
方法
我不清楚您想做什么,但我也建议您对代码做一些进一步的更改。通常不使用相同的方法初始化和播放剪辑
,因为这违背了剪辑
的预期用途。剪辑
用于存储可存储的声音。因此,将Clip
作为实例变量。然后,用自己的方法放置加载并打开剪辑的代码。并将调用start
或loop
的代码放在一个或多个单独的方法中,并且不要在播放结束时关闭剪辑
,除非您确定不再播放它
如果您使用clip.loop
,就不必为侦听器和计算迭代次数而烦恼。谢谢您的回答。我在播放声音方面没有任何问题,效果很好。我的问题是,当我不播放声音并且所有内容都关闭时,文件仍然被系统锁定,无法修改或删除。我只想能够在其他对话框窗口中加载不同的.wav格式的计算机,并将其保存为与初始文件相同的名称。虽然我关闭了文件,但看起来AudioInputStream仍然锁定该文件。我也尝试过使用Media和MediaPlayer,但同样的情况也发生了。也许文件命令仍然有效。尝试改用URL。我刚注意到你做的每件事都在一条“合理的线索”之内。很少需要处理声音——每次播放声音时都会启动新线程。对不起,我帮不了你,但是你做事的方式让我很困惑。我认为简化会大大有助于解决你的问题。也许试着制作一个简单的剪辑,调用它,播放它,让它被垃圾收集,然后看看你是否可以加载文件。我知道我在过去多次加载wav文件,但总是使用自己的音频输入流。这是非常复杂程序的一部分,不是声音播放器。这就是我使用线程的原因。程序必须运行并完成它的工作,有时它必须在不保持整个程序的情况下,以一些可配置的间隔按编程次数播放声音。然而,我试着只播放一次没有线的声音。一旦文件被播放,它将被“其他进程使用”,并且不能再被触摸。谢谢这和这个话题是一样的:它从来没有得到正确的答案