es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Una excepción de IO cuando intento obtener un InputStream conectado con un archivo dentro de un archivo jar en la API de Java Sound

Estoy escribiendo un método simple para reproducir sonidos utilizando Java Sound API. Mi idea es reproducir solo archivos .wav incluidos en el archivo JAR. Con imágenes, puedo obtener fácilmente un InputStream utilizando ClassLoader.getResourceAsStream() y cargar una imagen desde este flujo. Sin embargo, cuando uso el mismo enfoque con sonidos, obtengo una IOException.

Caused by: java.io.IOException: mark/reset not supported
    at java.base/java.util.zip.InflaterInputStream.reset(InflaterInputStream.java:290)
    at java.base/java.io.FilterInputStream.reset(FilterInputStream.java:224)
    at java.desktop/com.sun.media.sound.SunFileReader.getAudioFileFormat(SunFileReader.java:59)
    at java.desktop/com.sun.media.sound.WaveExtensibleFileReader.getAudioInputStream(WaveExtensibleFileReader.java:259)
    at java.desktop/javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1010)
    at ru.mrkefir.stepan.engine.sound.Audio.playImpl(Audio.java:34)

La causa es AudioSystem.getAudioInputStream() que uso desde el siguiente código:

AudioInputStream stream = AudioSystem.getAudioInputStream(
     Audio.class.getClassLoader().getResourceAsStream(path)
);
Clip clip = AudioSystem.getClip();
clip.open(stream);
clip.setFramePosition(0);
clip.start();

Verifico que el InputStream resultante se pueda leer y obviamente no es nulo. Según entiendo por la descripción de la excepción, Java Sound API y en particular la clase AudioSystem, que uso para obtener una instancia de AudioInputStream, intentan utilizar operaciones de marca o reinicio en el InputStream subyacente. Parece que estas operaciones no están permitidas en dichos flujos de entrada.

Estoy completamente confundido. Me resulta extraño que javax.sound.sampled.AudioSystem lea un InputStream de manera completamente diferente a javax.imageio.ImageIO (con ImageIO puedo leer imágenes de un archivo JAR sin problemas).

¿Cómo puedo solucionarlo? Obviamente, puedo leer un archivo regular, no desde el archivo JAR, pero si es posible, quiero leer los sonidos exactamente desde los archivos JAR.

He intentado ejecutar este código con Java 8.0.302-open y Java 16.0.2-open. Además, si este problema es específico de la plataforma, estoy usando Desktop Ubuntu 20.04 con Linux Kernel version 5.11.0-41-generic y, desafortunadamente, no tengo la oportunidad de probar este código en otras plataformas.

RESUELTO: Gracias a @filpa, la solución es envolver un InputStream obtenido por ClassLoader.getResourceAsStream() en un BufferedInputStream o cualquier otro InputStream que admita operaciones mark/reset.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para solucionar el problema con mark/reset not supported al utilizar AudioSystem.getAudioInputStream() para reproducir archivos .wav incluidos en un archivo jar, puedes intentar envolver el InputStream obtenido por ClassLoader.getResourceAsStream() en un BufferedInputStream.

    Aquí tienes un ejemplo de código:

    InputStream is = Audio.class.getClassLoader().getResourceAsStream(path);
    AudioInputStream stream = AudioSystem.getAudioInputStream(new BufferedInputStream(is));
    Clip clip = AudioSystem.getClip();
    clip.open(stream);
    clip.setFramePosition(0);
    clip.start();
    

    Al envolver el InputStream en un BufferedInputStream, proporciona las funcionalidades necesarias de mark/reset que el AudioInputStream requiere para leer correctamente los datos de audio del recurso en el archivo jar.

    Esto te permitirá reproducir archivos de audio desde el jar utilizando la API de Java Sound.

Comments are closed.