程序在Eclipse中完全运行,但在导出为Runnable JAR文件时不运行

时间:2013-07-28 20:23:33

标签: java eclipse jar

我有一个看起来像这样的主类:

package complete;

import java.io.File;
import java.io.*;
import javax.sound.sampled.*;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.BooleanControl;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.SourceDataLine;
import javax.swing.JFrame;

public class Main {

public static void main(String[] args) {
    JFrame frame = new JFrame("Presentation");
    frame.setSize(806, 506);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.add(new GameFrame());
    frame.setVisible(true);
sound = new File("Assets/BackgroundSound.wav"); // Write you own file location here and be aware that it need to be an .wav file

    new Thread(play).start();
}

static File sound;
static boolean muted = false; // This should explain itself
static float volume = 100.0f; // This is the volume that goes from 0 to 100
static float pan = 0.0f; // The balance between the speakers 0 is both sides and it goes from -1 to 1

static double seconds = 0.0d; // The amount of seconds to wait before the sound starts playing

static boolean looped_forever = true; // It will keep looping forever if this is true

static int loop_times = 0; // Set the amount of extra times you want the sound to loop (you don't need to have looped_forever set to true)
static int loops_done = 0; // When the program is running this is counting the times the sound has looped so it knows when to stop

final static Runnable play = new Runnable() // This Thread/Runnabe is for playing the sound
{
    public void run()
    {
        try
        {
            // Check if the audio file is a .wav file
            if (sound.getName().toLowerCase().contains(".wav"))
            {
                AudioInputStream stream = AudioSystem.getAudioInputStream(sound);

                AudioFormat format = stream.getFormat();

                if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED)
                {
                    format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                            format.getSampleRate(),
                            format.getSampleSizeInBits() * 2,
                            format.getChannels(),
                            format.getFrameSize() * 2,
                            format.getFrameRate(),
                            true);

                    stream = AudioSystem.getAudioInputStream(format, stream);
                }

                SourceDataLine.Info info = new DataLine.Info(
                        SourceDataLine.class,
                        stream.getFormat(),
                        (int) (stream.getFrameLength() * format.getFrameSize()));

                SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
                line.open(stream.getFormat());
                line.start();

                // Set Volume
                FloatControl volume_control = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
                volume_control.setValue((float) (Math.log(volume / 100.0f) / Math.log(10.0f) * 20.0f));

                // Mute
                BooleanControl mute_control = (BooleanControl) line.getControl(BooleanControl.Type.MUTE);
                mute_control.setValue(muted);

                FloatControl pan_control = (FloatControl) line.getControl(FloatControl.Type.PAN);
                pan_control.setValue(pan);

                long last_update = System.currentTimeMillis();
                double since_last_update = (System.currentTimeMillis() - last_update) / 1000.0d;

                // Wait the amount of seconds set before continuing
                while (since_last_update < seconds)
                {
                    since_last_update = (System.currentTimeMillis() - last_update) / 1000.0d;
                }

                //System.out.println("Playing!");

                int num_read = 0;
                byte[] buf = new byte[line.getBufferSize()];

                while ((num_read = stream.read(buf, 0, buf.length)) >= 0)
                {
                    int offset = 0;

                    while (offset < num_read)
                    {
                        offset += line.write(buf, offset, num_read - offset);
                    }
                }

                line.drain();
                line.stop();

                if (looped_forever)
                {
                    new Thread(play).start();
                }
                else if (loops_done < loop_times)
                {
                    loops_done++;
                    new Thread(play).start();
                }
            }
        }
        catch (Exception ex) { ex.printStackTrace(); }
    }
};



}

当我运行可运行的JAR时,框架将以正确的大小和标题打开,但屏幕为空白。

当我从命令行运行时出现此错误:

java.io.FileNotFoundException: Assets\BackgroundSound.wav <The system cannot find the path specified> 

at java.io.FileInputStream.open<Native Method>

at java.io.FileInputStream.<init><Unknown Source>

at com.sun.media.sound.WaveFloatFileReader.getAudioInputStream<Unknown Source>

at javax.sound.sampled.AudioSystem.getAudioInputStream<Unknown Source>

at complete.Main$1.run<Main.Java:50>

at java.lang.Thread.run<Unknown Source>

我从JAR中提取了文件,所有类,图像和WAV文件都在那里。

当我从Main类中删除声音部分并在Eclipse中运行时,程序会完全运行并且没有预期的声音。

当我将此版本导出为Runnable JAR时,我尝试运行它时会发生同样的事情,除非这次没有命令行错误。

3 个答案:

答案 0 :(得分:0)

要从jar加载文件,您需要使用getResources或getResourceAsStream。

答案 1 :(得分:0)

使用:

sound = new File(Main.class.getResource("Assets/BackgroundSound.wav").getPath());

答案 2 :(得分:0)

sound的数据不直接包含在磁盘上的文件中;它位于项目的jar文件中。因此,使用File访问它是不正确的。相反,请使用重载的AudioStream方法:

public static AudioInputStream getAudioInputStream(InputStream stream)
                                        throws UnsupportedAudioFileException,
                                               IOException
  

从提供的输入流中获取音频输入流。流必须指向有效的音频文件数据。此方法的实现可能需要多个解析器检查流以确定它们是否支持它。这些解析器必须能够标记流,读取足够的数据以确定它们是否支持流,如果没有,则将流的读指针重置为其原始位置。如果输入流不支持这些操作,则此方法可能会因IOException而失败。

您使用InputStream获得Class.getResourceAsStream(String name)。这将在类路径上查找,因此可以设置为在Eclipse和jar文件中都有效。最简单的方法是将声音文件移到您的类文件旁边,这样您就可以使用:

InputStream soundResource = Main.class.getResourceAsStream("BackgroundSound.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(soundResource);

抱歉 - 我需要编辑最后一部分 - 我忘了这一切都在main。除了最琐碎的程序之外,尽量不要这样做。相反,实例化该类并让实例执行操作。并将该类从Main重命名为SoundDemo。否则在三个月内你会对自己说:“我在哪里学习如何让Java播放声音呢?它是什么文件?它在Main?真的吗?”