天天看點

Android中資源檔案夾res/raw和assets的使用

*res/raw和assets的相同點:

1.兩者目錄下的檔案在打包後會原封不動的儲存在apk包中,不會被編譯成二進制。

*res/raw和assets的不同點:

1.res/raw中的檔案會被映射到R.java檔案中,通路的時候直接使用資源ID即R.id.filename;assets檔案夾下的檔案不會被映射到R.java中,通路的時候需要AssetManager類。

2.res/raw不可以有目錄結構,而assets則可以有目錄結構,也就是assets目錄下可以再建立檔案夾

*讀取檔案資源:

1.讀取res/raw下的檔案資源,通過以下方式擷取輸入流來進行寫操作

• InputStream is = getResources().openRawResource(R.raw.filename);      

2.讀取assets下的檔案資源,通過以下方式擷取輸入流來進行寫操作

• AssetManager am = null;  
• am = getAssets();  
• InputStream is = am.open("filename");      

在未知目錄下有哪些檔案,該去和擷取這些檔案的名稱并把檔案拷貝到目标目錄中呢?(用于内置檔案但不知道檔案名稱,需要篩選出想要的檔案然後拷貝到目标目錄中,推薦内置在assets檔案夾中)

1.res/raw目錄:
InputStream is = getResources().openRawResource(R.raw.filename);通過這個方法獲得raw中的檔案流,讀取大家應該都會。
 2.assets目錄:
 getAssets().list("");來擷取assets目錄下所有檔案夾和檔案的名稱,再通過這些名稱再讀取我們想要的檔案。      

上次說到Android中資源檔案夾res/raw和assets的使用,但是在讀取這兩個資源檔案夾中的檔案時會有一定的限制,即單個檔案大小不能超過1M,如果讀取超過1M的檔案會報"Data exceeds UNCOMPRESS_DATA_MAX (1314625 vs 1048576)"的IOException。

解決方法如下(假設我們現在要把一個超過1M的檔案在程式啟動時拷貝到sdcard中)

1.先把需要拷貝的大檔案分割成若幹個大小小于1M的小檔案(事先寫個程式來分隔或者使用一些工具,我這裡直接寫了個程式),把這些小檔案放在assets檔案夾中;2.在程式啟動時我們擷取這些小檔案的檔案名,當然我們得事先規定小檔案的命名方式友善我們來擷取這些檔案名;

3.通過獲得的小檔案名分别建立輸入流來合并成一個大檔案,并拷貝到sdcard中。

下面是解決方法中需要用到的一些代碼,僅供參考,不妨自己寫。分割大檔案的方法:

1.    
2.  public static void main(String[] args) throws Exception {  
3.      // 大檔案放置的路徑  
4.      String path = "D:/";  
5.      // 大檔案的檔案名稱  
6.      String base = "demo";  
7.      String ext = ".db";  
8.      // 以每個小檔案1024*1024位元組即1M的标準來分割  
9.      int split = 1024 * 1024;  
10.      byte[] buf = new byte[1024];  
11.      int num = 1;  
12.      // 建立輸入流  
13.      File inFile = new File(path + base + ext);  
14.      FileInputStream fis = new FileInputStream(inFile);  
15.      while (true) {  
16.          // 以"demo"+num+".db"方式來命名小檔案即分割後為demo1.db,demo2.db,。。。。。。  
17.          FileOutputStream fos = new FileOutputStream(new File(path + base  
18.                  + num + ext));  
19.          for (int i = 0; i < split / buf.length; i++) {  
20.              int read = fis.read(buf);  
21.              fos.write(buf, 0, read);  
22.              // 判斷大檔案讀取是否結束  
23.              if (read < buf.length) {  
24.                  fis.close();  
25.                  fos.close();  
26.                  return;  
27.              }  
28.          }  
29.          fos.close();  
30.          num++;  
31.      }  
32.  }      

擷取輸入流來合并檔案,我們這裡以assets檔案夾下的檔案為例,raw檔案夾下如何擷取輸入流請參考之前的那篇博文。

1.   
2. private void mergeApkFile(Context c, ArrayList<String> partFileList, String dst) throws IOException {  
3.     if (!new File(dst).exists()) {  
4.         OutputStream out = new FileOutputStream(dst);  
5.         byte[] buffer = new byte[1024];  
6.         InputStream in;  
7.         int readLen = 0;  
8.         for(int i=0;i<partFileList.size();i++){  
9.             // 獲得輸入流  
10.             in = c.getAssets().open(partFileList.get(i));  
11.             while((readLen = in.read(buffer)) != -1){  
12.                 out.write(buffer, 0, readLen);  
13.             }  
14.             out.flush();  
15.             in.close();  
16.         }  
17.         // 把所有小檔案都進行寫操作後才關閉輸出流,這樣就會合并為一個檔案了  
18.         out.close();  
19.     }  
20. }