【Android 儲存資料】Internal Storage 使用教學

【Android 儲存資料】Internal Storage 使用教學 - 封面圖

在 Android 安裝 APP 時,系統會自動在手機內部規劃一個專屬的目錄 (app-specific) 來儲存 APP 資料,這個目錄就是 Internal Storage,儲存在這個目錄之外的就稱為 External Storage。 Internal Storage 只有安裝的 APP 可以存取,無法與其他 APP 共享資料,也無法使用手機內建的檔案管理 APP 瀏覽檔案,如果 APP 是您開發的話,可以使用 Android Studio 內建的 Device File Explorer 工具來瀏覽檔案。 當 APP 解除安裝時,資料也會一併刪除,而在 Android 10 (API 29) 及以上版本中,這些位置會進行加密處理,進一步提升資料安全性。適合用來儲存 APP 執行時會用到的必要檔案,或較機密的資料

Internal Storage 是儲存在手機內部儲存空間,主要有兩個類型,一個是儲存永久檔案,另一個是儲存快取檔案,兩者在使用上皆無需任何權限就可以操作這些檔案。 早期手機容量通常遠小於 SD 卡,所以不建議將太多的資料放在 Internal Storage,而應放在 External Storage,雖然現在手機容量通常都很大,但還是應該合理的使用 Internal Storage 的空間。

1永久檔案

儲存路徑/data/data/[Package Name]/files/[檔名]

有時您可能會看到 /data/user/0/[Package Name] 目錄,這其實是當前 Android 帳號所存取的實際路徑。您可以把 /data/data/[Package Name] 目錄視為 /data/user/0/[Package Name] 目錄的捷徑。

寫入

                
                    public void writeFileToInternal(String fileName, String fileContents) throws IOException {
                        FileOutputStream outputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
                        outputStream.write(fileContents.getBytes());
                        outputStream.close();
                    }

                    writeFileToInternal("test", "測試資料");
                
            

讀取

                
                    public String readFileFromInternal(String fileName) throws IOException {
                        File file = new File(getFilesDir(), fileName);
                        FileInputStream inputStream = new FileInputStream(file);
                        BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        for (int result = bufferedStream.read(); result != -1; result = bufferedStream.read()) {
                            outputStream.write((byte) result);
                        }

                        // 關閉串流
                        inputStream.close();

                        // 回傳檔案字串
                        return outputStream.toString("UTF-8");
                    }

                    readFileFromInternal("test", "測試資料");
                
            

刪除

                
                    public void removeFileFromInternal(String fileName) {
                        File file = new File(getFilesDir(), fileName);
                        file.delete();
                    }

                    removeFileFromInternal("test");
                
            

2快取檔案

儲存路徑/data/data/[Package Name]/cache/[檔名]

寫入

                
                    public void writeCacheFileToInternal(String fileName, String fileContents) throws IOException {
                        // 方法ㄧ
                        File file = File.createTempFile(fileName, ".tmp", getCacheDir());

                        // 方法二
                        File file = new File(this.getCacheDir(), fileName);

                        FileOutputStream outputStream = new FileOutputStream(file);
                        outputStream.write(fileContents.getBytes());
                        outputStream.close();
                    }

                    writeCacheFileToInternal("test", "測試資料");
                
            

行 3:方法ㄧ使用 File.createTempFile() 方法,會在檔名 fileName 後面添加一串隨機數字,這是用來確保檔案唯一性,後續您必須使用 file.getName() 取得檔名,並將檔名儲存起來,否則後續很難再存取此檔案了。
行 6:方法二是我比較常用的方法,此方法不會加入隨機變數,可以使程式碼中的檔名與實際生成的檔案一致。

關於方法ㄧ及方法二的差異,以下舉一些例子,幫助您更了解其中的差異。

  • File.createTempFile("test", ".tmp")
    實際檔名 test1977042155964944352.tmp
  • File.createTempFile("test", ".txt")
    實際檔名 test1977042155964944352.txt
  • File.createTempFile("test", ".tmp", getCacheDir())
    實際檔名 test1977042155964944352.tmp
  • File.createTempFile("test", ".txt", getCacheDir())
    實際檔名 test1977042155964944352.txt
  • new File(this.getCacheDir(), "test")
    實際檔名 test
  • new File(this.getCacheDir(), "test.tmp")
    實際檔名 test.tmp
  • new File(this.getCacheDir(), "test.txt")
    實際檔名 test.txt

讀取

                
                    public String readCacheFileFromInternal(String fileName) throws IOException {
                        File file = new File(getCacheDir(), fileName);
                        FileInputStream inputStream = new FileInputStream(file);
                        BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        for (int result = bufferedStream.read(); result != -1; result = bufferedStream.read()) {
                            outputStream.write((byte) result);
                        }

                        // 關閉串流
                        inputStream.close();

                        // 回傳檔案字串
                        return outputStream.toString("UTF-8");
                    }

                    readCacheFileFromInternal("test", "測試資料");
                
            

行 2:與永久檔案只差在 getCacheDir() 方法,永久檔案是使用 getFilesDir() 方法。

刪除

                
                    public void removeCacheFileFromInternal(String fileName) {
                        File file = new File(getCacheDir(), fileName);
                        file.delete();
                    }

                    removeCacheFileFromInternal("test");
                
            

行 2:與永久檔案只差在 getCacheDir() 方法,永久檔案是使用 getFilesDir() 方法。

0 則留言