2013-02-10 168 views
3

我正在創建一個需要從文件讀取數據的應用程序。我最初使用BufferedReaderInputStreamReader從assets文件夾中讀取它,但我遇到了內存問題(請參閱Android: File Reading - OutOfMemory Issue)。一個建議是將資產文件夾中的數據複製到內部存儲器(而不是SD卡),然後通過RandomAccessFile訪問它。於是我擡起頭如何從資產內部存儲複製文件,我發現2個來源:Android:使用RandomAccessFile從內部存儲訪問文件

https://groups.google.com/forum/?fromgroups=#!topic/android-developers/RpXiMYV48Ww

http://developergoodies.blogspot.com/2012/11/copy-android-asset-to-internal-storage.html

我決定從第二個使用的代碼,並修改它爲我的文件。所以它看起來像這樣:

public void copyFile() { 
    //Open your file in assets 
    Context context = getApplicationContext(); 
    String destinationFile = context.getFilesDir().getPath() + File.separator + "text.txt"; 

    if (!new File(destinationFile).exists()) { 
     try { 
      copyFromAssetsToStorage(context, "text.txt", destinationFile); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

private void copyStream(InputStream input, OutputStream output) throws IOException { 
    byte[] buffer = new byte[1024]; 
    int length = Input.read(buffer); 
    while (length > 0) { 
     output.write(buffer, 0, length); 
     length = input.read(buffer); 
    } 
} 

private void copyFromAssetsToStorage(Context context, String sourceFile, String destinationFile) throws IOException { 
    InputStream inputStream = context.getAssets().open(sourceFile); 
    OutputStream outputStream = new FileOutputStream(destinationFile); 
    copyStream(inputStream , outputStream); 
    outputStream.flush(); 
    outputStream.close(); 
    inputStream.close(); 
} 

我假設這會將文件複製到應用程序的數據目錄中。我無法測試它,因爲我希望能夠使用RandomAccessFile訪問該文件。但是,我從來沒有做過這兩個任何一個(從資產複製文件和RandomAccessFile),所以我卡住了。這個應用程序的工作已陷入停滯狀態,因爲這是阻止我完成它的唯一因素。

任何人都可以提供更正,建議和如何使用RandomAccessFile訪問數據的正確實現嗎? (數據是字符串的列表的長度4-15個字符每行。)

編輯*

private File createCacheFile(Context context, String filename){ 
File cacheFile = new File(context.getCacheDir(), filename); 

    if (cacheFile.exists()) { 
     return cacheFile ; 
    } 

    InputStream inputStream = null; 
    FileOutputStream fileOutputStream = null; 

    try { 

     inputStream = context.getAssets().open(filename); 
     fileOutputStream = new FileOutputStream(cacheFile); 

     int bufferSize = 1024; 
     byte[] buffer = new byte[bufferSize]; 
     int length = -1; 
     while ((length = inputStream.read(buffer)) > 0) { 
      fileOutputStream.write(buffer,0,length); 
     } 

    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    finally { 
     try { 
      fileOutputStream.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     try { 
      inputStream.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    return cacheFile; 
} 

回答

1

1-從資產文件複製到所述高速緩存目錄

此代碼只是爲了舉例說明,你必須做適當的異常處理接近資源

private File createCacheFile(Context context, String filename){ 
    File cacheFile = new File(context.getCacheDir(), filename); 

    if (cacheFile.exists()) { 
     return cacheFile ; 
    } 


    InputStream inputStream = context.getAssets().open(filename); 
    FileOutputStream fileOutputStream = new FileOutputStream(cacheFile); 

    int bufferSize = 1024; 
    byte[] buffer = new byte[bufferSize]; 
    int length = -1; 
    while ((length = inputStream.read(buffer)) > 0) { 
    fileOutputStream.write(buffer,0,length); 
    } 

    fileOutputStream.close(); 
    inputStream.close(); 

    return cacheFile; 
} 

2-打開使用RandomAccessFile

File cacheFile = createCacheFile(context, "text.txt"); 
RandomAccessFile randomAccessFile = new RandomAccessFile(cacheFile, "r"); 

// Process the file 

randomAccessFile.close();  

在一個側面說明了文件,你應該遵循Java的命名約定,例如你的方法和變量名應以小寫字母開始,如copyFromAssetsToStoragedestinationFile

編輯:

你應該做一個獨立的try/catch每個close()操作,因此,如果一個失敗,其他都還得到執行,並檢查他們不是null

finally { 
    try { 
     if(fileOutputStream!=null){ 
      fileOutputStream.close();    
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    try { 
     if(inputStream!=null){ 
     inputStream.close();  
     }  
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
+0

感謝您的回覆。我想確保我得到這個權利。我是否正確實施了try/catch(請參閱編輯)?沒有錯誤,但這並不一定意味着它是正確的。另外,我是否必須執行任何類型的「清理」,例如每次使用後清除緩存? – 2013-02-11 01:42:07

+0

你應該在'try/catch'塊之外定義'fileOutputStream'和'inputStream',並在檢查它們不爲null之後在'final'塊中關閉它們(每個'close(你將需要另一個'try/catch' )'操作) – iTech 2013-02-11 01:44:24

+0

哇......呃......好的。我認爲這應該都在不同的線程?目前我有一個異步線程設置,所以我只是在async類的doInBackground方法中有第2步代碼? – 2013-02-11 01:47:15

相關問題