在 Eclipse 中播放音频文件 IDE;但不是 JAR 文件
Audio file plays in Eclipse IDE; but NOT as JAR file
我正在使用的音频文件可以在这里找到:http://www.orangefreesounds.com/loud-alarm-clock-sound/
这是我的文件结构在我的 Eclipse 中的样子 IDE:
当我 运行 在我的 IDE 中时,音频文件播放得非常好,但当我将它导出为 JAR 文件时却没有。我已经检查并发现音频文件在 JAR 文件中。
我正在使用终端命令 java -jar Sandbox.jar &
来 运行 JAR 文件。该程序似乎能够找到文件(因为它没有抛出 IOException),但似乎无法执行播放。
为什么会出现这个问题,我该如何解决?
奇怪的更新
好的,实际上,JAR 文件可以在 cmd
或 PowerShell
Windows 8.1 中的 运行 时播放音频文件,但在 Windows 8.1 中则不能由于某种原因 Ubuntu 14.04 的终端。一直以来,我一直在尝试 运行 Ubuntu 14.04.
中的 JAR 文件
奇怪的更新#2
我已确认 JAR 文件仅在 Windows 8.1
系统上运行的问题。这个问题中的两个代码片段都不起作用,而 MadProgrammer 的两个解决方案都有效。
最小、完整且可验证的示例(不适用于 Windows 或 Ubuntu)
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;
public class Sandbox
{
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
URL url = Sandbox.class.getResource("/sound-effects/alarmSoundClip.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
}
}
尝试的解决方案 #1(不适用于 Windows 或 Ubuntu)
一个尝试的解决方案(如 Andrew Thompson 所建议的那样)是写 this.getClass().getResource( ... )
而不是 Sandbox.class.getResource( ... ):
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;
public class Sandbox
{
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
new Sandbox();
}
public Sandbox() throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
URL url = this.getClass().getResource("/sound-effects/alarmSoundClip.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
}
}
在 clip.start()
之后添加 clip.drain()
对我来说似乎没问题(IDE 和命令行有无 &
)
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Sandbox {
public static void main(String[] args) {
try {
URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
System.out.println("Drain...");
clip.drain();
System.out.println("...Drained");
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException exp) {
exp.printStackTrace();
}
}
}
现在,话虽如此,我发现 drain
过去有点不可靠,尤其是当有多个声音播放时,在这种情况下我倾向于使用 LineListener
例如...
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Sandbox {
protected static final Object LOCK = new Object();
public static void main(String[] args) {
try {
URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.addLineListener(new LineListener() {
@Override
public void update(LineEvent event) {
System.out.println(event.getType());
if (event.getType() == LineEvent.Type.STOP) {
synchronized (LOCK) {
LOCK.notify();
}
}
}
});
clip.start();
synchronized (LOCK) {
LOCK.wait();
}
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException exp) {
exp.printStackTrace();
}
}
}
我正在使用的音频文件可以在这里找到:http://www.orangefreesounds.com/loud-alarm-clock-sound/
这是我的文件结构在我的 Eclipse 中的样子 IDE:
当我 运行 在我的 IDE 中时,音频文件播放得非常好,但当我将它导出为 JAR 文件时却没有。我已经检查并发现音频文件在 JAR 文件中。
我正在使用终端命令 java -jar Sandbox.jar &
来 运行 JAR 文件。该程序似乎能够找到文件(因为它没有抛出 IOException),但似乎无法执行播放。
为什么会出现这个问题,我该如何解决?
奇怪的更新
好的,实际上,JAR 文件可以在 cmd
或 PowerShell
Windows 8.1 中的 运行 时播放音频文件,但在 Windows 8.1 中则不能由于某种原因 Ubuntu 14.04 的终端。一直以来,我一直在尝试 运行 Ubuntu 14.04.
奇怪的更新#2
我已确认 JAR 文件仅在 Windows 8.1
系统上运行的问题。这个问题中的两个代码片段都不起作用,而 MadProgrammer 的两个解决方案都有效。
最小、完整且可验证的示例(不适用于 Windows 或 Ubuntu)
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;
public class Sandbox
{
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
URL url = Sandbox.class.getResource("/sound-effects/alarmSoundClip.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
}
}
尝试的解决方案 #1(不适用于 Windows 或 Ubuntu)
一个尝试的解决方案(如 Andrew Thompson 所建议的那样)是写 this.getClass().getResource( ... )
而不是 Sandbox.class.getResource( ... ):
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;
public class Sandbox
{
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
new Sandbox();
}
public Sandbox() throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
URL url = this.getClass().getResource("/sound-effects/alarmSoundClip.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
}
}
在 clip.start()
之后添加 clip.drain()
对我来说似乎没问题(IDE 和命令行有无 &
)
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Sandbox {
public static void main(String[] args) {
try {
URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
System.out.println("Drain...");
clip.drain();
System.out.println("...Drained");
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException exp) {
exp.printStackTrace();
}
}
}
现在,话虽如此,我发现 drain
过去有点不可靠,尤其是当有多个声音播放时,在这种情况下我倾向于使用 LineListener
例如...
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Sandbox {
protected static final Object LOCK = new Object();
public static void main(String[] args) {
try {
URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.addLineListener(new LineListener() {
@Override
public void update(LineEvent event) {
System.out.println(event.getType());
if (event.getType() == LineEvent.Type.STOP) {
synchronized (LOCK) {
LOCK.notify();
}
}
}
});
clip.start();
synchronized (LOCK) {
LOCK.wait();
}
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException exp) {
exp.printStackTrace();
}
}
}