Android數據存儲(一)

一)文件存儲方式

通過java裏的文件讀取流和寫入流來對安卓的文件進行讀寫操作

安卓應用程序資源分類可以分爲兩大類,assets和res.其中res保存的文件大都會被編譯,並且會被賦予資源id,這樣我們可以在程序中通過id來訪問res類的資源,res按不同用途可以分爲anim,animator,color,drawable,layout,raw,menu,values,xml這九種。

1)讀取assets中的文件數據:assets類資源放在工程目錄的assets子目錄下,它裏面保存的是一些原始文件,可以以任何方式來進行組織,這些文件最終會原裝不動的打包在apk文件裏。

訪問assets文件資源通過getAssets().open()來打開文件名,注意inputStreamReader()裏面設置編碼格式爲utf-8,這樣統一編碼格式,防止亂碼出現。

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.get_assets:
                try {
                    InputStream in=getResources().getAssets().open("info.txt");
                    InputStreamReader isr=new InputStreamReader(in,"utf-8");
                    BufferedReader bfr=new BufferedReader(isr);
                    System.out.println(bfr.readLine());
                    String s="";
                    while ((s=bfr.readLine())!=null){//讀取文件內容
                        System.out.println(s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;

2)讀取raw文件:raw文件和assets文件一樣都是原封不動的打包在apk文件,不過raw會被賦予資源id,,這樣我們就可以在程序裏通過id來訪問他們。

通過openRawResource()傳入文件的id來訪問,傳入R.raw.filename

  case R.id.get_raw:

//                try {
//                    InputStream in = getResources().openRawResource(R.raw.inforaw);
//                    InputStreamReader isr = new InputStreamReader(in, "utf-8");
//                    BufferedReader brf = new BufferedReader(isr);
//                    String str = "";
//                    while ((str=brf.readLine())!=null){
//                        System.out.println(str);
//                    }
//                } catch (UnsupportedEncodingException e) {
//                    e.printStackTrace();
//                }catch (IOException e){
//                    e.printStackTrace();
//                }
//                break;

3)讀寫內部存儲的文件數據

存儲在內部還是外部

所有的Android設備均有兩個文件存儲區域:"internal" 與 "external" 。 這兩個名稱來自於早先的Android系統,當時大多設備都內置了不可變的內存(internal storage)及一個類似於SD card(external storage)這樣的可卸載的存儲部件。之後有一些設備將"internal" 與 "external" 都做成了不可卸載的內置存儲,雖然如此,但是這一整塊還是從邏輯上有被劃分爲"internal"與"external"的。只是現在不再以是否可卸載進行區分了。 下面列出了兩者的區別:

  • Internal storage:

    • 總是可用的
    • 這裏的文件默認只能被我們的app所訪問。
    • 當用戶卸載app的時候,系統會把internal內該app相關的文件都清除乾淨。
    • Internal是我們在想確保不被用戶與其他app所訪問的最佳存儲區域。
  • External storage:

    • 並不總是可用的,因爲用戶有時會通過USB存儲模式掛載外部存儲器,當取下掛載的這部分後,就無法對其進行訪問了。
    • 是大家都可以訪問的,因此保存在這裏的文件可能被其他程序訪問。
    • 當用戶卸載我們的app時,系統僅僅會刪除external根目錄(getExternalFilesDir())下的相關文件。
    • External是在不需要嚴格的訪問權限並且希望這些文件能夠被其他app所共享或者是允許用戶通過電腦訪問時的最佳存儲區域。

我們可以讀寫data目錄下的內部存儲數據,比如我們把在EditText裏面寫的文字寫入我們定義的一個filename,然後在data目錄下可以找到filename的文件裏存放着我們EditText的內容,並且可以讀取出來。

模式指定爲MODE_PRIVATE別的程序就不能訪問這個文件。

系統默認程序的安裝位置是內部,我們也可以在Manifest裏面修改。當程序卸載後,其內部文件也會被刪除。

我們的app的internal storage 目錄以app的包名作爲標識存放在Android文件系統的特定目錄下[data/data/com.example.xx]。 從技術上講,如果文件被設置爲可讀的,那麼其他app就可以讀取該internal文件。然而,其他app需要知道包名與文件名。若沒有設置爲可讀或者可寫,其他app是沒有辦法讀寫的。因此我們只要使用了MODE_PRIVATE ,那麼這些文件就不可能被其他app所訪問。

case R.id.get_write:
                try {
                    FileOutputStream fileOutputStream=openFileOutput(filename, Context.MODE_PRIVATE);
                    OutputStreamWriter  outputStreamWriter=new OutputStreamWriter(fileOutputStream,"utf-8");
                    outputStreamWriter.write(write.getText().toString());
                    outputStreamWriter.flush();
                    fileOutputStream.flush();
                    outputStreamWriter.close();
                    fileOutputStream.close();
                    Toast.makeText(MainActivity.this,"寫入完成",Toast.LENGTH_SHORT).show();

                } catch (FileNotFoundException e) {

                }catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }catch (IOException e) {
                    e.printStackTrace();
                }


                break;

            case R.id.read:

                try {

                    FileInputStream fileInputStream=openFileInput(filename);
                    InputStreamReader inputStreamReader=new InputStreamReader(fileInputStream,"utf-8");
                    char[] input=new char[fileInputStream.available()];//文件長度設置爲字符數組長度
                    inputStreamReader.read(input);
                    inputStreamReader.close();
                    fileInputStream.close();
                    String str=new String(input); //字符數組轉換爲字符串
                    show.setText(str);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }catch (IOException e) {
                    e.printStackTrace();
                }


                break;

4)讀取外部存儲的文件數據

寫數據到外部存儲,需要聲明權限(在android4.4之後外部存儲的讀寫都不再需要聲明權限)

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

如果聲明瞭寫權限,那麼程序默認有讀取的權限。

否則如果程序只需要讀取的權限,我們應該聲明讀取權限

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
因爲存儲在外部的數據有可能發生變化,比如sd卡拔掉,所以在讀寫之前我們應該先對其可用性狀態進行檢查,使用getExternalStorageState()進行檢查,如果返回值是MEDIA_MOUNTED,那麼可以進行讀寫

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;
}

存儲在外部的數據分爲public 和private兩種,public files在程序卸載時應該保留,比如被程序拍攝的照片或者下載的文件。private files在程序卸載的時候應該刪除,因爲這些緩存文件對其他程序來說並沒有任何意義。

以public 形式向外部存儲寫入數據:getExternalStoragePublicDirectory()來構建一個File對象表示存儲在External Storage目錄,其包含一個指定文件類型的參數,以便於與其他public 文件區別,比如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;
}

以private形式存儲,getExternalFileDir來獲取File對象,表示存儲在app下的參數文件夾下,比如下面例子的(albumName)。這個文件夾會在程序卸載的時候刪除。

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;
}


這樣將文件保存在外部存儲之後,就可以進行讀取的操作。


二)SharedPreference的使用

SharedPreference是一種輕型的數據存儲形式,使用鍵值對來讀寫,並且通過SharedPrefrence.Editor來存儲。

其存儲位置在/data/data/com.xxxxxxx(package name)/shared-prefs目錄。

我們可以通過getSharedPreFerences()和getPreFerences()來創建Shared Preferences文件,前者需要在參數裏設置一個文件名,並且通過Context來執行;後者不需要設置文件名,而且是通過Activity來執行

private SharedPreferences   preference=getPreferences(Activity.MODE_PRIVATE);
	private Editor  editor=preference.edit();

sharedPreferences()的讀和寫操作:

@Override
	public void onClick(View v) {
        
		switch (v.getId()) {
		case R.id.write:
			editor.putString(KEY, input.getText().toString());
		    if (editor.commit()) {
				Toast.makeText(MainActivity.this, "寫入數據成功",Toast.LENGTH_SHORT).show();
			}
			
			
			break;
		case R.id.read:
			String data=preference.getString(KEY, "數據不存在");
			Toast.makeText(MainActivity.this,data, Toast.LENGTH_SHORT).show();
			
			break;
		default:
			break;
		}
	}








發佈了49 篇原創文章 · 獲贊 27 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章