JavaFX音频在JAR文件中无法播放问题咨询
这个问题的核心原因很明确:Eclipse导出可运行JAR时使用了自定义的rsrc:协议,但JavaFX的Media类只支持标准的URL协议(比如file:、jar:)。
为什么Eclipse里运行正常?
在Eclipse开发环境中,你的音频文件是磁盘上的物理文件,getClass().getResource("/Sounds/WindowsError.wav")返回的是file:开头的URL,Media可以正常解析这种标准协议,所以音频能播放。
但当你用Eclipse的「Runnable JAR File」导出功能时,它会用一种自定义的rsrc:协议来打包和访问资源(这是Eclipse为了简化类加载做的特殊处理),而JavaFX的Media组件并没有实现对这个非标准协议的支持,因此抛出了UnsupportedOperationException: Unsupported protocol "rsrc"错误。
解决方法
方法1:改用标准类加载器获取资源
替换getClass().getResource()为ClassLoader.getSystemResource(),它会返回标准的jar:协议URL,Media可以正常识别:
try{ // 使用系统类加载器获取资源,返回标准jar协议URL URL resource = ClassLoader.getSystemResource("Sounds/WindowsError.wav"); Media audio = new Media(resource.toString()); MediaPlayer mediaPlayer = new MediaPlayer(audio); mediaPlayer.play(); }catch(Exception e){ e.printStackTrace(); }
方法2:将资源提取到临时文件播放
如果方法1还是有问题,可以把JAR中的音频资源提取到临时文件,再用file:协议访问,这种方式兼容性最好:
import java.io.File; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.StandardCopyOption; // ... try { // 获取资源输入流 InputStream inputStream = getClass().getResourceAsStream("/Sounds/WindowsError.wav"); // 创建临时文件,程序退出时自动删除 File tempFile = File.createTempFile("temp-audio", ".wav"); tempFile.deleteOnExit(); // 将输入流复制到临时文件 Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); // 用临时文件的URL创建Media对象 Media audio = new Media(tempFile.toURI().toString()); MediaPlayer mediaPlayer = new MediaPlayer(audio); mediaPlayer.play(); } catch (Exception e) { e.printStackTrace(); }
方法3:换用普通JAR打包方式
不要用Eclipse的「Runnable JAR File」导出,而是选择「JAR File」导出,然后手动通过命令行运行:
java -cp your-jar-file.jar your.main.ClassName
这种方式会使用标准的jar:协议访问资源,不会出现rsrc:的问题。
额外检查
确保你的音频文件在导出的JAR中路径正确:打开JAR文件,确认里面有/Sounds/WindowsError.wav这个文件,Eclipse导出时要勾选包含资源文件夹。
内容的提问来源于stack exchange,提问作者Rodrigo Albuquerque

