问题描述
我正在尝试使用Javax.sound播放.wav文件。 一切正常,文件按预期播放,最后关闭剪辑并关闭AudioInputStream。但是,此后文件仍处于锁定状态(使用中),并且在没有异常的情况下我无法触摸它:java.nio.file.FileSystemException:alerting.wav:该进程无法访问该文件,因为该文件正在被另一个进程使用。 / p>
下面是代码示例:
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,ex);
} catch (IOException ex) {
Main.syslog(Level.WARNING,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 Sound Event Dispatcher”正在运行。我认为这是使文件锁定的原因。 知道如何解决这个问题吗?谢谢
解决方法
剪辑的API状态:
请注意,某些行一旦关闭,便无法重新打开。尝试去 重新打开这样的行将始终导致
LineUnavailableException
。
我将提出一些其他建议。
不是使用File
,而是一种更好的加载音频资源的方法是使用class.getResource
方法。此方法返回一个URL
,您可以将其作为参数传递给AudioSystem.getAudioInputStream
方法。
我不清楚您要做什么,但是我还建议对您的代码做一些进一步的更改。通常不会用相同的方法初始化和播放Clip
,因为它违背了Clip
的预期用途。 Clip
用于保留在内存中的声音。因此,将Clip
设置为实例变量。然后,以自己的方法放置加载并打开Clip
的代码。并将调用start
或loop
的代码放在一个或多个单独的方法中,除非确定您永远不会使用,否则不要在播放结束时关闭Clip
再次播放。
如果使用clip.loop
,则不必打扰侦听器并计算迭代次数。