2013-03-31 62 views
4

我可以使用標記wiki頁面上的「播放Clip」解決方案來讀取和播放聲音。但是,對於頻繁播放的聲音(例如,快速激光槍聲,腳步聲等),每當您想要創建新的Clip時,我都會打開流並重新讀取文件。所以,我試圖將讀取的文件緩存到byte[]中,隨後從緩存中加載它們。使用jar文件中的字節數組緩存聲音

裝載部分很簡單:

// Get a BAIS. 
ByteArrayInputStream bais = new ByteArrayInputStream(cache.get(fileName)); 

// Convert to an audio stream. 
AudioInputStream ais = AudioSystem.getAudioInputStream(bais); 

然而,最初獲得該文件的內容到一個字節數組被證明是一個挑戰。問題是我試圖從包含的文件中讀取聲音.jar –因此使用java.io.File不是一個選項(據我所知),以及我見過的各種解決方案(下面的鏈接)不適用。

在我看來,最難的部分將獲得文件的長度來創建字節數組,而不使用java.io.File。我可以用Scanner讀取字節,但我需要將它們讀入一些數組。我應該只使用ArrayList<Byte>? (請參閱下面的「次優示例」。)

所以,我的問題:什麼是我可以讀取嵌入文件到byte[]重複訪問以後的最佳方式?

限制

  • 我必須要能夠在jar文件中訪問文件。我相信這將我限制爲Class.getResourceClass.getResourceAsStream
  • 文件字節應存儲在標準的byte[]變量中。
  • 我寧願這樣做沒有引入不必要的依賴項,如番石榴或Apache Commons。到目前爲止,我的整個項目都是在Java(JDK6)中,我想保持這種狀態。

我試過了什麼?

我使用RandomAccessFile嘗試,就像這樣:

// Get the file. 
RandomAccessFile f = new RandomAccessFile(fullPath, "r"); 

// Create a byte array. 
theseBytes = new byte[(int) f.length()]; 

// Read into the array. 
f.read(theseBytes); 

// Close the file. 
f.close(); 

// Put in map for later reference. 
byteCache.put(fullPath, theseBytes); 

然而,顯然這隻能用於磁盤引用的文件;我得到以下錯誤:

java.io.FileNotFoundException: \path\to\sound\in\jar\file.wav (The system cannot find the path specified)

次優例

雖然這個例子工作,我不認爲一個ArrayList是做到這一點的最好辦法,由於不斷調整大小等。

// Get a stream. 
InputStream s = clazz.getResourceAsStream(fullPath); 

// Get a byte array. 
ArrayList<Byte> byteArrayList = new ArrayList<Byte>(); 

// Create a storage variable. 
int last = 0; 

// Loop. 
while ((last = s.read()) != -1) { 
    // Get it. 
    byteArrayList.add((byte) last); 
} 

// Create a byte array. 
theseBytes = new byte[byteArrayList.size()]; 

// Loop over each element. 
for (int i = 0; i < theseBytes.length; i++) { 
    // Set the byte. 
    theseBytes[i] = byteArrayList.get(i); 
} 

上閱讀

+0

優秀的問題格式! –

回答

3

試試這個:

InputStream is = new BufferedInputStream(getClass().getResourceAsStream(name)); 
ByteArrayOutputStream out = new ByteArrayOutputStream(); 
for (int b; (b = is.read()) != -1;) { 
    out.write(b); 
} 
byte[] a = out.toByteArray(); 

其中name.jar內文件的路徑。

+0

有趣而聰明。謝謝。 – wchargin