亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

【Android Developers Training】 25. 保存文件

系統(tǒng) 2203 0

注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛安卓而產(chǎn)生了翻譯的念頭,純屬個人興趣愛好。

原文鏈接: http://developer.android.com/training/basics/data-storage/files.html


Android使用的文件系統(tǒng)和其它平臺上使用的磁盤文件系統(tǒng)比較類似。這節(jié)課將描述如何通過 File 的APIs對Android文件系統(tǒng)進行讀寫文件。

一個文件對象適合于按既定的順序讀或者寫大量數(shù)據(jù), 而非跳躍式地進行。例如,它適合于圖像文件或者任何在網(wǎng)絡(luò)上交換的數(shù)據(jù)。

這堂課將展示如何在你的應(yīng)用中,執(zhí)行與基本文件相關(guān)的任務(wù)。我們假設(shè)你熟悉Linux文件系統(tǒng)基礎(chǔ)知識,以及 java.io 中標(biāo)準(zhǔn)文件輸入/輸出流的APIs。

?

一). 選擇內(nèi)存或外存

所有Android設(shè)備有兩個文件存儲區(qū)域:“ 內(nèi)部 internal )”和“ 外部 external )”存儲。這兩個名字的由來要追溯到早期的Android,那時大多數(shù)設(shè)備提供內(nèi)置的 非易失性存儲器(內(nèi)存),加上一個可移除的閃存介質(zhì),比如迷你SD卡(外存)。一些設(shè)備將永久存儲空間劃分為“內(nèi)部”和“外部”兩個部分,所以即使沒有閃存介質(zhì),仍然會有兩個存儲空間。與此同時,不管外存是否是可移除的,對于API來說沒有差異。下面將列舉出每個存儲空間的特性。

內(nèi)存:

  • 永遠可以獲取的到
  • 默認情況下,存儲在這里的文件只有你的應(yīng)用自身能獲取到
  • 當(dāng)用戶卸載了你的應(yīng)用,系統(tǒng)會從內(nèi)存中刪除所有該應(yīng)用的相關(guān)文件

綜上所述,當(dāng)你期望你的文件不會被用戶或者其他應(yīng)用獲取時,內(nèi)存將是最好的選擇。

外存:

  • 它并不能永遠都可獲得,因為用戶可以將外存作為一個USB存儲而掛載起來,并且在一些情況下會把它從設(shè)備上移除
  • 存儲在這里的文件可被任意訪問,而不在你的控制之內(nèi)
  • 當(dāng)用戶刪除了你的應(yīng)用時,只有在你將文件存儲在通過 getExternalFilesDir() 方法所得到的目錄下時,系統(tǒng)才會刪除你的文件

綜上所述,外存適合于存儲那些對訪問沒有限制的文件,以及你希望和其他應(yīng)用共享的文件,或者你希望用戶可以通過電腦來獲取到的文件。

Tip:

雖然默認情況下應(yīng)用匯存儲在內(nèi)存,但你可以定義清單文件中的“ android:installLocation ”這一屬性字段,這樣你的應(yīng)用就可以存儲在外存上。當(dāng)APK文件大小很大,同時用戶擁有一個比內(nèi)存空間要大的外存時,用戶會期望能夠這么做。更多信息可以閱讀: App Install Location

?

二). 獲得操控外存的權(quán)限許可

為了獲得寫入外存的權(quán)限,你必須在你的清單文件( manifest file )中聲明“ WRITE_EXTERNAL_STORAGE ”的授權(quán)許可:

      
        <
      
      
        manifest 
      
      
        ...
      
      
        >
      
      
        <
      
      
        uses-permission 
      
      
        android:name
      
      
        ="android.permission.WRITE_EXTERNAL_STORAGE"
      
      
        />
      
      
        

    ...


      
      
        </
      
      
        manifest
      
      
        >
      
    

Caution:

目前,所有的應(yīng)用都可以在沒有特殊權(quán)限許可的情況下讀取外存。然而這將會在未來的某個版本下改變。如果你的應(yīng)用需要讀取外存(而不需要寫),那么你需要聲明“ READ_EXTERNAL_STORAGE ”的權(quán)限許可,以此保證你的應(yīng)用在未來版本更新以后還可以正常工作。務(wù)必在改變生效之前,現(xiàn)在就聲明這個權(quán)限許可。

        
          <
        
        
          manifest 
        
        
          ...
        
        
          >
        
        
          <
        
        
          uses-permission 
        
        
          android:name
        
        
          ="android.permission.READ_EXTERNAL_STORAGE"
        
        
          />
        
        
          

    ...


        
        
          </
        
        
          manifest
        
        
          >
        
      

然而,如果你的應(yīng)用使用 WRITE_EXTERNAL_STORAGE ”的授權(quán)許可,那么它暗示了同時還擁有讀外存的權(quán)限。

在內(nèi)存中保存文件不需要任何權(quán)限許可。你的應(yīng)用永遠都具有讀和寫在內(nèi)存中其自身所對應(yīng)的目錄的權(quán)限。

?

三). 在內(nèi)存中保存一個文件

當(dāng)將一個文件存入內(nèi)存時,你可以通過調(diào)用以下任一一種方法來取得合適的目錄作為一個 File 對象:

  • getFilesDir() :返回一個 File 對象,它 代表了你的應(yīng)用所擁有的內(nèi)存中的一個目錄。
  • getCacheDir() :返回一個 File 對象,它代表了存放應(yīng)用的臨時緩存文件的內(nèi)存目錄。請確保刪除每一個不再需要的文件,同時制定一個任何時刻你能使用的存儲空間的大小限制,比如1MB。如果系統(tǒng)在運行時存儲空間不足,它可能會在沒有任何警告的情況下刪除你的緩存文件。

為了在上述任何一個目錄中創(chuàng)建文件,你可以使用構(gòu)造函數(shù) File() ,傳遞給它上述兩個方法中的一個來特定你的內(nèi)存中的目錄路徑。例如:

      File file = 
      
        new
      
       File(context.getFilesDir(), filename);
    

另外,你可以調(diào)用 openFileOutput() 來獲得一個文件輸出流,以此將數(shù)據(jù)寫入你的內(nèi)存目錄中的一個文件。例如:

      String filename = "myfile"
      
        ;

String string 
      
      = "Hello world!"
      
        ;

FileOutputStream outputStream;




      
      
        try
      
      
         {

  outputStream 
      
      =
      
         openFileOutput(filename, Context.MODE_PRIVATE);

  outputStream.write(string.getBytes());

  outputStream.close();

} 
      
      
        catch
      
      
         (Exception e) {

  e.printStackTrace();

}
      
    

或者,如果你需要緩存一個文件,你應(yīng)該使用 createTempFile() 方法。例如,下面的方法從一個 URL 中提取出文件名,然后利用該名字創(chuàng)建一個文件,在你的應(yīng)用的內(nèi)存目錄中:

      
        public
      
      
         File getTempFile(Context context, String url) {

    File file;

    
      
      
        try
      
      
         {

        String fileName 
      
      =
      
         Uri.parse(url).getLastPathSegment();

        file 
      
      = File.createTempFile(fileName, 
      
        null
      
      
        , context.getCacheDir());

    
      
      
        catch
      
      
         (IOException e) {

        
      
      
        //
      
      
         Error while creating file
      
      
            }

    
      
      
        return
      
      
         file;

}
      
    

Note:

你的應(yīng)用的內(nèi)存目錄的位置是在Android文件系統(tǒng)中的一個特殊的位置,它由你的應(yīng)用的包名所指定。從技術(shù)上來講,如果你將文件的模式設(shè)置為可讀,那么另一個應(yīng)用是可以讀取你的內(nèi)部文件的。然而,這是在其他應(yīng)用指導(dǎo)你的應(yīng)用的包名以及相應(yīng)的文件名的情況下。其他應(yīng)用瀏覽你的內(nèi)部目錄并且沒有讀或?qū)懙臋?quán)力,除非你顯示地將文件設(shè)置為了可讀或可寫。所以只要你為你存放在內(nèi)存中文件使用了 MODE_PRIVATE 標(biāo)識,它們將永遠無法被其他應(yīng)用所訪問到。

?

四). 在外存上保存一個文件

因為外存可能是無法獲得的,比如當(dāng)用戶已經(jīng)把存儲掛載至PC上,或者已經(jīng)移除了提供外存的SD卡。你應(yīng)該在每次訪問它之前先確認對應(yīng)的卷是否存在。你可以通過調(diào)用 getExternalStorageState() 來查詢外存的狀態(tài)。如果返回的狀態(tài)是 MEDIA_MOUNTED ,那么你可以讀和寫你的文件。例如,下面的方法用來確認存儲是否可用:

      
        /*
      
      
         Checks if external storage is available for read and write 
      
      
        */
      
      
        public
      
      
        boolean
      
      
         isExternalStorageWritable() {

    String state 
      
      =
      
         Environment.getExternalStorageState();

    
      
      
        if
      
      
         (Environment.MEDIA_MOUNTED.equals(state)) {

        
      
      
        return
      
      
        true
      
      
        ;

    }

    
      
      
        return
      
      
        false
      
      
        ;

}




      
      
        /*
      
      
         Checks if external storage is available to at least read 
      
      
        */
      
      
        public
      
      
        boolean
      
      
         isExternalStorageReadable() {

    String state 
      
      =
      
         Environment.getExternalStorageState();

    
      
      
        if
      
       (Environment.MEDIA_MOUNTED.equals(state) ||
      
        

        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {

        
      
      
        return
      
      
        true
      
      
        ;

    }

    
      
      
        return
      
      
        false
      
      
        ;

}
      
    

雖然外存可被用戶或其他應(yīng)用修改,但是你在這里存儲的文件可以分為兩類:

公有文件(Public files):

這些文件可以被用戶和其他應(yīng)用任意訪問。當(dāng)用戶卸載了你的應(yīng)用,這些文件將仍然保留。例如,你的應(yīng)用所拍攝的圖片或其他下載的文件。

私有文件(Private files):

屬于你的應(yīng)用的合法文件,用戶卸載你的應(yīng)用時,這些文件也會被同時刪除。雖然從技術(shù)上說,因為這些文件存儲于外存,所以它們可以被用戶或其他應(yīng)用訪問到,但實際上這些文件在你的應(yīng)用范圍之外向用戶提供任何數(shù)據(jù)。當(dāng)用戶卸載了你的應(yīng)用時,系統(tǒng)會刪除所有你的應(yīng)用外部私有目錄下的文件。此類文件的例子有:你應(yīng)用所下載的額外的資源文件或者臨時的多媒體文件。

如果你希望在外存中存儲公有文件,使用 getExternalStoragePublicDirectory() 來獲得一個 File 對象,它代表了外存上一個合適的目錄。這個方法接受一個參數(shù),該參數(shù)指定了你希望存儲的文件類型,這樣它們就能與其他公有文件一起被統(tǒng)一地管理了,文件類型諸如: DIRECTORY_MUSIC 或者 DIRECTORY_PICTURES 。

      
        public
      
      
         File getAlbumStorageDir(String albumName) {

    
      
      
        //
      
      
         Get the directory for the user's public pictures directory. 
      
      

    File file = 
      
        new
      
      
         File(Environment.getExternalStoragePublicDirectory(

            Environment.DIRECTORY_PICTURES), albumName);

    
      
      
        if
      
       (!
      
        file.mkdirs()) {

        Log.e(LOG_TAG, 
      
      "Directory not created"
      
        );

    }

    
      
      
        return
      
      
         file;

}
      
    

如果你希望存儲屬于你應(yīng)用的私有文件,那么你可以調(diào)用 getExternalFilesDir() 來獲得一個合適的目錄,同時傳遞給它一個名字來說明目錄類型(如果你喜歡的話)。每個通過這種方式創(chuàng)建的目錄會添加到一個父目錄下,以此把你的應(yīng)用的所有外存文件都封裝起來。當(dāng)用戶卸載應(yīng)用時,他們會被刪除。

例如,下面的方法可以用來為一個個人相冊創(chuàng)建一個目錄:

      
        public
      
      
         File getAlbumStorageDir(Context context, String albumName) {

    
      
      
        //
      
      
         Get the directory for the app's private pictures directory. 
      
      

    File file = 
      
        new
      
      
         File(context.getExternalFilesDir(

            Environment.DIRECTORY_PICTURES), albumName);

    
      
      
        if
      
       (!
      
        file.mkdirs()) {

        Log.e(LOG_TAG, 
      
      "Directory not created"
      
        );

    }

    
      
      
        return
      
      
         file;

}
      
    

如果沒有一個預(yù)定義的子目錄名和你的文件相符合,那么你可以調(diào)用 getExternalFilesDir() ,并且將參數(shù)傳遞為“ null ”。這樣將會返回你應(yīng)用在外存上的私有目錄路徑的根路勁位置。

記住, getExternalFilesDir() 所創(chuàng)建的目錄是在一個當(dāng)用戶卸載你的應(yīng)用時,會被一起刪除的目錄下的。如果你所保存的文件在用戶卸載應(yīng)用后仍然需要存在(比如你的應(yīng)用是一個相機軟件,用戶希望保留這些相片),那么你應(yīng)該使用 getExternalStoragePublicDirectory()

不管你使用的是 getExternalStoragePublicDirectory() (用于共享的文件),還是 getExternalFilesDir() (用于私有的文件),使用API常量提供的目錄名(諸如 DIRECTORY_PICTURES )是很重要的。這些目錄名保證了系統(tǒng)會正確地處理這些文件。例如,存儲于 DIRECTORY_RINGTONES 下的文件會被系統(tǒng)的多媒體掃描器分類為鈴聲而不是音樂。

?

五). 查詢空余空間

如果你能提前知道你要存儲多大的數(shù)據(jù),那么你將知道是否有足夠的空間來存儲這些數(shù)據(jù),從而避免 IO異常( IOException )。通過 調(diào)用 getFreeSpace() 或者 getTotalSpace() 這兩個方法可以實現(xiàn)上述的預(yù)期。這兩個方法分別提供了在存儲卷內(nèi)的當(dāng)前可用空間和總空間。這些信息還可以用來避免向存儲卷內(nèi)填充超出閾值數(shù)量的數(shù)據(jù)。

然而,系統(tǒng)不會保證你可以寫入和 getFreeSpace() 所返回的可用空間一樣大小的數(shù)據(jù)。如果返回的數(shù)量比你希望存儲的數(shù)量多了幾兆,或者文件系統(tǒng)的使用率小于90%,那么繼續(xù)執(zhí)行是沒有問題的。否則你可能無法寫入數(shù)據(jù)。

Note:

你不必在你存儲文件之前檢查可用空間的大小。你可以嘗試直接寫入文件,然后當(dāng)異常發(fā)生時捕捉 IOException 。你需要這么做如果你不知道你具體需要多少空間。例如,如果你在保存之前轉(zhuǎn)變了文件的編碼(把PNG格式的圖片轉(zhuǎn)換為JPEG,此時你無法預(yù)知文件的大?。?。

?

六). 刪除一個文件

你應(yīng)該將不再需要的文件刪除。刪除文件最直接的方法是對文件對象自身調(diào)用 delete() 。

      myFile.delete();
    

如果文件存儲于內(nèi)存,你也可以通過 Context 來定位,然后調(diào)用 deleteFile() 刪除文件:

      myContext.deleteFile(fileName);
    

Note:

當(dāng)用戶卸載了你的應(yīng)用,Android系統(tǒng)會刪除如下文件:

然而,你要定期手動地刪除所有通過 getCacheDir() 創(chuàng)建的臨時文件以及其它你不再需要的文件。

【Android Developers Training】 25. 保存文件


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲成在人天堂一区二区 | 精品哟啊呦v视频在线观看 精品哟哟国产在线观看 | 天天操夜夜骑 | 免费看国产精品麻豆 | 国产欧美日韩综合 | 国产精品久久久久一区二区 | 九九热免费在线观看 | 亚洲国产精品成人综合色在线婷婷 | 一级做受毛片免费大片 | 久久久久久久久久久观看 | 久久免费区一区二区三波多野 | 激情一区二区三区 | 久久最稳定资源站在线 | 一本大道香蕉中文在线高清 | 日日摸夜夜添夜夜添欧美毛片 | 亚洲一区二区中文 | 色久综合在线 | 日本一区二区三区在线 观看网站 | 天天干视频在线 | 99久久精品男女性高爱 | 免费看一级毛片欧美 | 91中文| 九九精品视频一区二区三区 | 四虎avtom影院 | 亚洲一区二区三区高清视频 | 国产精品久久久久不卡绿巨人 | 欧美精品亚洲精品日韩专区 | 欧美中文字幕视频 | 在线观看香蕉免费啪在线观看 | 国产在线91观看免费观看 | 成人在线免费观看 | 色狠狠狠狠综合影视 | 色视频在线免费看 | 91视频香蕉视频 | 日日爽日日操 | 久久艹免费视频 | 国语国产真人对白毛片 | 99久久在线 | 中文字幕在线综合 | 九九热在线免费观看 | 亚洲欧美日韩国产精品 |