2011-03-23 193 views
0

我有一個應用程序使用它從Socket InputStream獲取的字節數組創建多個文件。當我只保存一個文件時,該文件可以完美保存,但如果我保存一個文件,然後重新實例化文件流並保存另一個文件,則第一個文件會損壞,第二個文件會完全保存。我在一個文本編輯器中打開了這兩個文件,它似乎(關於...)第一個文件的前五分之一是空格,但第二個文件已滿,並且它們都具有相同的大小屬性(9,128,731字節)。下面的例子是塞納里奧的重複,但具有相同腐敗的結果:Android FileOutputStream創建損壞的文件

FileOutputStream outStream; 
outStream = new FileOutputStream("/mnt/sdcard/testmp3.mp3"); 
File file = new File("/mnt/sdcard/test.mp3"); 
FileInputStream inStream = new FileInputStream(file); 
byte[] buffer = new byte[9128731]; 
inStream.read(buffer); 
outStream.write(buffer, 0, buffer.length); 
inStream.close(); 
outStream.flush(); 
outStream.close(); 
outStream = null; 
outStream = new FileOutputStream("/mnt/sdcard/testmp32.mp3"); 
outStream.write(buffer, 0, buffer.length); 
inStream.close(); 
outStream.flush(); 
outStream.close(); 
outStream = null; 

我在一個普通的Java應用程序嘗試這個確切的代碼和文件都被保存沒有問題。有誰知道爲什麼Android這樣做?

任何幫助,將不勝感激

+0

第一次寫入後輸出「buffer」的內容,看看它是否是您期望的內容。我懷疑這是問題所在。 – 2011-03-23 02:57:44

+0

另外,爲什麼在使用'outStream.write(buffer)'時使用'outStream.write(buffer,0,buffer.length)'? – 2011-03-23 03:01:19

回答

0

如果任何人有同樣的問題,並想知道如何解決它,我發現問題是由我的SD卡引起的。我買了一塊32GB的金士頓SD卡,就在昨天,我決定再次嘗試運行相同的代碼,接受使用內部存儲器,而且一切正常。我也嘗試過它的股票2GB SD卡,它也很完美。我很高興知道我的代碼工作良好,但有點沮喪,我花了50美元在有缺陷的存儲卡上。感謝每個人的輸入。

1

我看,可以讓你開始調試一些潛在的問題:

  1. 你寫第一輸出流關閉輸入流之前。這有點奇怪。

  2. 您無法使用文本編輯器準確測量兩個二進制文件之間的相似性/差異。你需要看看在十六進制編輯器中的文件(或更好,Audacity

  3. 我會用BufferedOutputStream所建議的是Android文檔: out = new BufferedOutputStream(new FileOutputStream(file)); http://developer.android.com/reference/java/io/FileOutputStream.html

  4. 隨着調試技術,打印的內容第一次寫入後buffer。另外,inStream.read()返回int。我會另外比較這與buffer.length,並確保它們是相同的。無論如何,除非你有一個非常好的理由,否則我只會撥打write(buffer)而不是write(buffer, 0, buffer.length)

-tjw

+0

謝謝你們所有的建議,不幸的是,當我嘗試他們時,我得到了同樣的結果。我似乎已經找到了腐敗的來源 – 2011-03-23 04:58:15

+0

如果我打開手機本身的文件,他們都打開罰款,如果我在應用程序上「強行關閉」,然後將手機作爲磁盤驅動器,presto!這些文件是免費的腐敗!但是,如果我在活動中調用完成(),則將手機安裝爲磁盤驅動器,第一個顯示已損壞。有沒有辦法讓應用程序,因爲缺乏更好的術語,在沒有關閉的情況下「放開」文件?再次感謝 – 2011-03-23 05:07:07

0

您假設你想要的read()通話將讀取的字節數。這是不正確的。該方法可以從1到buffer.length字節的任意位置進行自由讀取。這就是爲什麼你應該使用總是使用返回值來確定實際讀取的字節數。有很多流式教程會告訴你如何從java流中正確讀取(即如何完全填充你的緩衝區)。

5

由於jtahlborn提到你不能假設InputStream.read(byte[])將總是讀取任意數量的字節,只要你想。你應該避免使用這麼大的字節數組來一次寫出。至少不是沒有緩衝,你可能會溢出一些東西。您可以通過像這樣複製文件來處理這些問題並節省一些內存:

File inFile = new File("/mnt/sdcard/test.mp3"); 
File outFile = new File("/mnt/sdcard/testmp3.mp3"); 
FileInputStream inStream = new FileInputStream(inFile); 
FileOutputStream outStream = new FileOutputStream(outFile); 
byte[] buffer = new byte[65536]; 
int len; 
while ((len = inStream.read(buffer)) != -1) { 
    outStream.write(buffer, 0, len); 
} 
inStream.close(); 
outStream.close();