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
- app:應用的apk檔案存放位置
- 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的實際目錄,因為系統不同路徑會有差異