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.id.filename);
2.讀取assets下的文件資源,通過以下方式獲取輸入流來進行寫操作
AssetManager am = null ; am = getAssets(); InputStream is = am.open("filename" );
在未知目錄下有哪些文件,該去和獲取這些文件的名稱並把文件拷貝到目標目錄中呢?
String[] files = getAssets().list("");
來獲取assets目錄下所有文件夾和文件的名稱,再通過這些名稱再讀取我們想要的文件。
Android 對asset與raw的限制
在讀取這兩個資源文件夾中的文件時會有一定的限制,即單個文件大小不能超過1M ,如果讀取超過1M的文件會報 “Data exceeds UNCOMPRESS_DATA_MAX (1314625 vs 1048576)“ 的IOException。
如何解決呢:
首先想到的是分割文件,再去合併並文件。
假設我們現在要把一個超過1M的文件在程序啓動時拷貝到sdcard中
1.先把需要拷貝的大文件分割成若干個大小小於1M的小文件(事先寫個程序來分隔或者使用一些工具,我這裏直接寫了個程序),把這些 小文件放在assets文件夾中。
2.在程序啓動時我們獲取這些小文件的文件名,當然我們得事先規定小文件的命名方式方便我們來獲取這些文件名。
3.通過獲得的小文件名分別建立輸入流來合併成一個大文件,並拷貝到sdcard中。
public static void main(String[] args) throws IOException { //需要分割的文件放置的路徑 String path = "E:/"; //需要分割的文件的文件名稱 String base = "demo"; //需要分割的文件的後綴名 String ext = ".db"; //以每個小文件1024*1024字節即1M的標準來分割 int split = 1024 * 1024; byte[] buf = new byte[1024]; int num = 1; //建立輸入流 File inFile = new File(path + base + ext); FileInputStream fis = new FileInputStream(inFile); while (true) { //以"demo"+num+".db"方式來命名小文件即分割後爲demo1.db,demo2.db,。。。。。。 FileOutputStream fos = new FileOutputStream(new File(path + base + num + ext)); for (int i = 0; i < split / buf.length; i++) { int read = fis.read(buf); fos.write(buf, 0, read); // 判斷大文件讀取是否結束 if (read < buf.length) { fis.close(); fos.close(); return; } } fos.close(); num++; } }
獲取輸入流來合併文件,我們這裏以assets文件夾下的文件爲例
AssetManager assetManager = getAssets(); String[] data = assetManager.list(""); mergeFile(this, data, pathinfo);
/** * 合併文件 * @param c * @param partFileList 小文件名集合 * @param dst 目標文件路徑 * @throws IOException * */ public static void mergeFile(Context c, String[] partFileList, String dst) throws IOException { if (!new File(dst).exists()) { OutputStream out = new FileOutputStream(dst); byte[] buffer = new byte[1024]; InputStream in; int readLen = 0; for(int i=0;i<partFileList.length;i++){ // 獲得輸入流 ,注意文件的路徑 in = c.getAssets().open(partFileList[i]); while((readLen = in.read(buffer)) != -1){ out.write(buffer, 0, readLen); } out.flush(); in.close(); } // 把所有小文件都進行寫操作後才關閉輸出流,這樣就會合併爲一個文件了 out.close(); } }