1. 程式人生 > >Android進階:android本地資料操作—步驟2:Android本地檔案操作

Android進階:android本地資料操作—步驟2:Android本地檔案操作

本地資料儲存

Android常用資料儲存

  • 1. SharedPreferences儲存資料
  • 2. 檔案儲存(內部,外部)
  • 3. SQLite資料庫儲存
  • 4. ContentProvider儲存資料
  • 5. 網路儲存資料

一、SharedPreferences儲存資料 

SharedPreferences

•用於存放一些類似登入的配置資訊 • 本質上是一個xml檔案,是通過類似鍵值對的方式存放資訊 • 位於程式私有目錄中,即data/data/[packageName]/shared_prefs

 特點: * (1)以鍵值對的形式儲存到data/data/應用程式包名/shared_prefs目錄的XXX.xml檔案中 * (2)目前支援的資料型別有String int float boolean long * (3)不支援自定義的Object * (4)通常用來儲存App上的使用者配置資訊.如:是否震動,是否開啟背景音樂 小遊戲積分 使用者賬號密碼資訊

SharedPreferences操作模式

  • MODE_APPEND: 追加方式儲存

  • MODE_PRIVATE: 私有方式儲存,其他應用無法訪問

  • MODE_WORLD_READABLE: 可被其他應用讀取

  •  MODE_WORLD_WRITEABLE:可被其他應用寫入

案例實現:

儲存資訊到sharedPreference中

SharedPreferences share = getSharedPreferences("myshare", MODE_PRIVATE);
                    //2.獲取Editor物件
                    SharedPreferences.Editor editor = share.edit();
                    //3.儲存資訊
                    editor.putString("account", accountStr);
                    editor.putString("pwd", pwdStr);
                    //4.指定提交操作
                    editor.commit();

讀取SharedPreference中的資訊

  /**
         * 自動讀取SharedPreference的資料
         */
        //1獲取Sharedpreference物件
        SharedPreferences share=getSharedPreferences("myshare",MODE_PRIVATE);
        //2根據key獲取內容(引數1:key,引數2:當對應key不存在時返回引數2 的內容作為預設值)
        String accStr=share.getString("account","");
        String pwdStr=share.getString("pwd","");
        //讓控制元件顯示sharedpreference的資訊
        account.setText(accStr);
        pwd.setText(pwdStr);

完整案例:

public class ShareActivity extends AppCompatActivity  {

    private EditText account;
    private EditText pwd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_share);
        account = findViewById(R.id.account);
        pwd = findViewById(R.id.pwd);
        /**
         * 自動讀取SharedPreference的資料
         */
        //1獲取Sharedpreference物件
        SharedPreferences share=getSharedPreferences("myshare",MODE_PRIVATE);
        //2根據key獲取內容(引數1:key,引數2:當對應key不存在時返回引數2 的內容作為預設值)
        String accStr=share.getString("account","");
        String pwdStr=share.getString("pwd","");
        //讓控制元件顯示sharedpreference的資訊
        account.setText(accStr);
        pwd.setText(pwdStr);
        /**
         * 儲存資料到sharedpreference
         */
        findViewById(R.id.login_bt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //1獲取兩個輸入框的內容
                String accountStr=account.getText().toString();
                String pwdStr=pwd.getText().toString();
                //2.驗證
                   //2.1驗證成功,儲存資訊到sharepreference
                   //1.獲取sharedpreference物件(引數1:檔名稱,引數2:操作模式)
                if(accountStr.equals("admin")&&pwdStr.equals("123")) {
                    SharedPreferences share = getSharedPreferences("myshare", MODE_PRIVATE);
                    //2.獲取Editor物件
                    SharedPreferences.Editor editor = share.edit();
                    //3.儲存資訊
                    editor.putString("account", accountStr);
                    editor.putString("pwd", pwdStr);
                    //4.指定提交操作
                    editor.commit();
                    Toast.makeText(ShareActivity.this, "驗證成功", Toast.LENGTH_SHORT).show();
                }
                   //2.2驗證失敗,提示使用者
                else
                Toast.makeText(ShareActivity.this,"驗證失敗",Toast.LENGTH_SHORT).show();

            }
        });
    }

}

 位於程式私有目錄中,即data/data/[packageName]/shared_prefs/myshare.xml

外部儲存ExternalStorage

記憶體:裝置實際的容量

內部儲存:檔案儲存在內部儲存中,只能被該應用使用如:SharedPreference

* Internal Storage特點: * 1.內部儲存總是可用的 * 2.內部儲存的檔案預設只能被當前應用程式訪問,它是私有的 * 3.如果App解除安裝,內部儲存檔案也會被刪除 * 4.如果檔案只提供給當前的應用程式訪問,那麼放到內部儲存中比較合適 * 5.內部儲存器的讀取速度最快且內部儲存空間十分珍貴,開發中需要合理使用 *

外部儲存ExternalStorage的特點

* 1.外部儲存不見得總是可用的: 例如:SD卡被移除了 * 2.外部儲存是全域性可見的,存放到外部儲存中的檔案可以被當前裝置中所有能夠操作該檔案的app訪問 * 3.為了更好的管理外部儲存,Android系統進行了更細緻的劃分:公共的外部儲存和私有的外部儲存,當app解除安裝的時候 * 公共的外部儲存中的檔案不會被刪除,私有外部儲存的檔案會被刪除 * 4.如果你當前檔案需要分享給其它的app訪問或者使用,檔案需要長久儲存,檔案比較大,或者檔案的安全性不做具體要求時,可以考慮使用外部儲存

  •  storage或者mnt資料夾
  •  Environment.getExternalStorageDirectory() //獲取外部儲存的檔案目錄
  •  公有目錄(DCIM、DOWNLOAD等)//可以被其他應用訪問
  •  私有目錄(Android/data/應用包名)//隨應用解除安裝而解除安裝

外部儲存的動態許可權(android6.0後要動態請求許可權)

一、讀寫檔案的時候要獲取許可權

1.在AndroidManifest.xml中宣告許可權

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

2.android6.0之後要在動態申請許可權

    //android6.0之後要動態獲取許可權
    private void checkPermission(Activity activity) {
        // Storage Permissions
        final int REQUEST_EXTERNAL_STORAGE = 1;
        String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE};

        try {
            //檢測是否有寫的許可權
            int permission = ActivityCompat.checkSelfPermission(DownLoadActivity.this,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 沒有寫的許可權,去申請寫的許可權,會彈出對話方塊
                ActivityCompat.requestPermissions(DownLoadActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

• ContextCompat.checkSelfPermission(context,permission) • ActivityCompat.requestPermissions(activity,permissions,code)

案例:

public class ExternalActivity extends AppCompatActivity {

    private EditText infoEdit;
    private TextView txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_external);
        infoEdit = findViewById(R.id.info_Edit);
        txt = findViewById(R.id.show_txt);
        //動態新增許可權
        checkPermission(this);
    }
    //操作方法
    public void operate(View v) {
        //判斷記憶體卡是否存在
        if (Environment.getExternalStorageState().equals("mounted")) {
            //獲取外部儲存的的絕對路徑
            String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/text.txt";
            //檢視一下路徑
            Log.e("TAG", path);
            switch (v.getId()) {
                //儲存內容
                case R.id.save_btn:
                    //新建text.txt檔案
                    File file = new File(path);
                    //如果檔案不存在,則建立
                    try {
                        if (!file.exists()) {
                            file.createNewFile();
                        }
                        //建立檔案輸入流寫入資料
                        //引數1:檔案路徑,引數2:可以拼接
                        FileOutputStream fos = new FileOutputStream(path, true);
                        String str = infoEdit.getText().toString();
                        //以位元組流的方式寫進去
                        fos.write(str.getBytes());
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                    //讀取內容
                case R.id.read_btn:
                    //檔案輸入流讀取資料
                    try {
                        FileInputStream fis=new FileInputStream(path);
                        byte[] b=new byte[1024];
                        //返回實際讀取長度
                        int len=fis.read(b);
                        //利用位元組陣列生成字串
                        String str=new String(b,0,len);
                        //顯示在文字框上
                        txt.setText(str);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
            }

        }
    }
    //android6.0之後要動態獲取許可權
    private void checkPermission(Activity activity) {
        // Storage Permissions
        final int REQUEST_EXTERNAL_STORAGE = 1;
        String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE};

        try {
            //檢測是否有寫的許可權
            int permission = ActivityCompat.checkSelfPermission(ExternalActivity.this,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 沒有寫的許可權,去申請寫的許可權,會彈出對話方塊
                ActivityCompat.requestPermissions(ExternalActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

儲存路徑: /storage/emulated/0/text.txt 

 獲取外部儲存的目錄(私有目錄)

好處

  • 應用被解除安裝後,這兩個目錄的內容也會被清除掉
  • 不需要任何許可權就可以操作

• Context.getExternalFilesDir(String type);//需要長時間儲存的資料

String type是Environment下的檔案型別 獲取到 SDCard/Android/data/包名/files/ 目錄

• Context.getExternalCacheDir();//臨時儲存的資料 獲取到 SDCard/Android/data/包名/cache/目錄

內部儲存InternalStorage

  • 內部儲存,簡稱為記憶體
  • 通過DDMS-->File Explorer可以找到,資料夾叫做data
  • 記憶體中有兩個資料夾:app,data
  1. app:應用的apk檔案存放位置
  2. data:應用包名的資料夾

* Internal Storage特點:

* 1.內部儲存總是可用的 * 2.內部儲存的檔案預設只能被當前應用程式訪問,它是私有的 * 3.如果App解除安裝,內部儲存檔案也會被刪除 * 4.如果檔案只提供給當前的應用程式訪問,那麼放到內部儲存中比較合適 * 5.內部儲存器的讀取速度最快且內部儲存空間十分珍貴,開發中需要合理使用 *

獲取內部儲存的目錄(不需要設定許可權就可以讀寫操作)

• Context.getFilesDir() 獲取/data/data/包名/files (files:放的是普通資料)

• Context.getCacheDir() 獲取/data/data/包名/cache(cache:放的是快取資料)

與上面外部儲存的操作除了路徑不一樣幾乎一樣的操作

不需要許可權

//操作方法
    public void operate(View v) {
            String path = InternalActivity.this.getFilesDir().getPath()+"/text.txt";
            //檢視一下路徑
            Log.e("TAG", path);
            switch (v.getId()) {
                //儲存內容
                case R.id.save_btn:
                    //新建text.txt檔案
                    File file = new File(path);
                    //等價File file = new File(getFilesDir(),"text.txt");
                    //如果檔案不存在,則建立
                    try {
                        if (!file.exists()) {
                            file.createNewFile();
                        }
                        //建立檔案輸入流寫入資料
                        //引數1:檔案路徑,引數2:可以拼接
                        FileOutputStream fos = new FileOutputStream(path, true);
                        String str = infoEdit.getText().toString();
                        //以位元組流的方式寫進去
                        fos.write(str.getBytes());
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                //讀取內容
                case R.id.read_btn:
                    //檔案輸入流讀取資料
                    try {
                        FileInputStream fis=new FileInputStream(path);
                        byte[] b=new byte[1024];
                        //返回實際讀取長度
                        int len=fis.read(b);
                        //利用位元組陣列生成字串
                        String str=new String(b,0,len);
                        //顯示在文字框上
                        txt.setText(str);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
            }

        }

FileNotFound異常解決方案

1. 檢查下錯誤提示中的路徑是否存在

2. 檢查許可權是否處理正確 3. 確認裝置是否有SDCard

DDMS中data、SDCard目錄無法展開

1. 模擬器需要更改只讀許可權,有的真機data目錄需要root

2. Environment.getExternalStorageDirectory()的獲取目 錄才是SDCard的實際目錄,因為系統不同路徑會有差異