android的資料儲存(1)(SharedPreference、File)
一、有些時候程式有少量的資料需要儲存時,而且格式簡單,是普通的字串,標量等,對於這種資料android提供了SharedPreference進行儲存。
二、SharedPreference儲存的資料是簡單的key--value對,SharedPreference介面主要負責,讀取應用程式的SharedPreference資料,而SharedPreference是沒有寫的能力,只有讀的能力。
由於SharedPreference是介面,是無法直接建立例項,只有通過Context提供的getSharedPreferences(String name,int mode)
name:為資料儲存的檔名
mode:可以有三個,但是其中有兩個是不安全的,android已經不再推薦了。所以mode用:MODE_PRIVATE
1、boolean contains(String key):判斷SharedPreference是否包含特定的key
2、abstract Map<String,?> getAll():獲取SharedPreference中的全部key--value對3、
3、boolean getXxx(String key, xx defValue):獲取SharedPreference指定的key--value,如果存在value則返回,如果不存在就返回defValue預設值。其中xx可以是boolean,flaot,int,long,String等。
三、要實現資料的寫入,要使用Editor物件,此物件是通過SharedPreference呼叫edit()方法得到、Editor物件提供如下的方法對資料的寫入。
1、SharedPreference.Editor clear():清空SharedPreference裡面的所有資料
2、SharedPreference.Editor putXxx(String key,xxx value):向SharedPreference裡面存入指定key對的資料,xxx可以是boolean,flaot,int,long,String等。
3、SharedPreference.Editor remove(String key):刪除SharedPreference裡面指定的key對資料項
4、boolean commit():當Editor編輯完成後,呼叫該方法提交修改
例項:對SharedPreference資料進行操作
1、xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/write" android:text="write"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/read" android:text="read"/> </LinearLayout>
2、activity
public class SharedPreferencesActivity extends AppCompatActivity { SharedPreferences sharedPreferences; SharedPreferences.Editor editor; static int count; public void onCreate(Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.sharedpreferences_activity); sharedPreferences=getSharedPreferences("crazyit",MODE_PRIVATE); //sharedPreferences為介面,無法直接建立,呼叫context中的方法,例項化sharedPreferences,進行對資料的讀 editor=sharedPreferences.edit(); //呼叫方法獲得Editor物件,對資料進行寫 Button write=findViewById(R.id.write); Button read=findViewById(R.id.read); count=sharedPreferences.getInt("count",0); write.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"+"hh:mm:ss"); editor.putString("time",sdf.format(new Date())); //寫入日期 editor.putInt("random",(int)(Math.random()*100)); //寫入一個整數 editor.putInt("count",++count); //寫入count editor.commit(); //提交修改 } }); read.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //進行讀 String time=sharedPreferences.getString("time",null); int random=sharedPreferences.getInt("random",0); int count1=sharedPreferences.getInt("count",0); Toast.makeText(SharedPreferencesActivity.this,time+" "+random+" "+count1,Toast.LENGTH_SHORT).show(); } }); } }
四、File儲存
一、Context提供瞭如下的兩種方式開啟程式資料檔案的io流
1、FileInputStream openFileInput(String name):開啟應用程式資料檔案下的name檔案對應輸入流,對於讀資料
2、FileOutputStream openFileOutput(String name,int mode):開啟應用程式的資料檔案下name檔案對應的輸入流,對應寫資料,
其中mode對應三個模式,但是其中兩個已經不推薦使用,所以mode:MODE_PRIVATE
二、Context還提供瞭如下的幾種方式訪問應用程式的資料檔案
1、getDir(String name,int mdoe):在應用程式的資料資料夾下獲取或建立name對應的子目錄
2、File getFilesDir():獲取應用程式的資料檔案的絕對路徑
3、String[] fileList():返回應用程式資料夾下的全部檔案
4、deleteFile(String):刪除應用程式的資料檔案指定的檔案
向程式資料資料夾內輸入資料:
//以追加的方式開啟資料夾的輸入流 FileOutputStream fos=openFileOutput(FILE_NAME,MODE_PRIVATE); //將FileOutputStream封裝成printStream PrintStream ps=new PrintStream(fos); //輸出內容到檔案 ps.print(content); ps.close();
嚮應用程式資料檔案讀資料
//開啟name程式資料檔案流輸入流 FileInputStream fil=openFileInput(FILE_NAME); //用於接收每次讀出的資料 byte[] buff=new byte[1024]; int hasRead=0; //讀取出來的全部資料 StringBuilder builder=new StringBuilder(); while((hasRead=fil.read(buff))>0){ //判斷資料是否讀完 builder.append(new String(buff,0,hasRead)); } //關閉檔案流 fil.close();
例項:程式寫如資料到程式資料夾內,在讀取資料夾裡面的內容
public class FileActivity extends AppCompatActivity{ private String FILE_NAME="/crazyit.bin"; EditText editText1; EditText editText2; protected void onCreate(Bundle saveInstanceSate) { super.onCreate(saveInstanceSate); LinearLayout linearLayout=new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); Button read=new Button(this); Button write=new Button(this); read.setText("read"); write.setText("write"); editText1=new EditText(this); editText2=new EditText(this); linearLayout.addView(write); linearLayout.addView(editText1); linearLayout.addView(read); linearLayout.addView(editText2); setContentView(linearLayout); read.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { editText2.setText(read()); } }); write.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { write(editText1.getText().toString()); editText1.setText(""); } }); } private String read(){ //嚮應用程式的資料資料夾read try{ FileInputStream fil=openFileInput(FILE_NAME); byte[] buff=new byte[1024]; int hasRead=0; StringBuilder builder=new StringBuilder(); while((hasRead=fil.read(buff))>0){ builder.append(new String(buff,0,hasRead)); } //關閉檔案流 fil.close(); return builder.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private void write(String content) { //嚮應用程式的資料資料夾write try{ FileOutputStream fos=openFileOutput(FILE_NAME,MODE_PRIVATE); //將FileOutputStream封裝成printStream PrintStream ps=new PrintStream(fos); ps.print(content); ps.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
五、讀取SD卡上的檔案
一、為了更好地存取應用程式地大檔案,應用程式需要讀寫SD卡上的檔案,SD卡大大地擴充了手機地儲存功能。分為幾個步驟。
1、呼叫Environment的getExteranlStorageState():方法判斷手機是否插入SD卡,並且應用程式具有讀寫的SD卡的許可權。
//如果手機已插入sd卡,且應用程式具有對鞋SD卡的能力,下面返回false
Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)
2、呼叫Environment的getExternalStorageDirectory()方法來獲取外部儲存器,也就是SD卡的目錄
3、使用FileInputStream,FileOutputStream ,FileRead或者FileWrite(),方法來讀寫SD卡
4、讀寫SD卡是一個危險許可權,需要在androidManifest.xml檔案中宣告許可權
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> //sd卡中刪除檔案許可權
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> //sd卡中讀寫檔案許可權
SD卡讀:
//如果手機插入SD卡,而且應用程式具有訪問sd卡的許可權 if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //獲取sd卡對應的儲存目錄 File sdCardDir=Environment.getExternalStorageDirectory(); //獲取指定檔案的輸入流 FileInputStream fis=new FileInputStream(sdCardDir.getCanonicalPath()+FILE_NAME); //將指定的輸入流包裝成BBufferedReader BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(fis)); StringBuilder builder=new StringBuilder(""); String line=null; while ((line=bufferedReader.readLine())!=null){ builder.append(line); } bufferedReader.close(); return builder.toString(); }
SD卡寫:
if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //獲取sd卡對應的儲存目錄 Toast.makeText(FileActivity.this,"有許可權",Toast.LENGTH_SHORT).show(); File sdCardDir=Environment.getExternalStorageDirectory(); File targetFile=new File(sdCardDir.getCanonicalPath()+FILE_NAME); Toast.makeText(FileActivity.this,sdCardDir.getCanonicalPath()+FILE_NAME,Toast.LENGTH_SHORT).show(); //將指定檔案建立RandomAccessFile物件 //這裡使用RandomAccessFile向SD卡中指定追加內容,如果使用FileOutputStream向指定檔案寫資料會將原有的檔案內容清空,而不是追加的方式 RandomAccessFile raf=new RandomAccessFile(targetFile,"rw"); //將檔案的指標移動到最後面 raf.seek(targetFile.length()); //輸出檔案內容 raf.write(content.getBytes()); Toast.makeText(FileActivity.this,"完成",Toast.LENGTH_SHORT).show(); raf.close(); }
例項:讀寫sd卡中的資料
public class FileActivity extends AppCompatActivity{ private String FILE_NAME="/crazyit.bin"; EditText editText1; EditText editText2; protected void onCreate(Bundle saveInstanceSate) { super.onCreate(saveInstanceSate); LinearLayout linearLayout=new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); Button read=new Button(this); Button write=new Button(this); read.setText("read"); write.setText("write"); editText1=new EditText(this); editText2=new EditText(this); linearLayout.addView(write); linearLayout.addView(editText1); linearLayout.addView(read); linearLayout.addView(editText2); setContentView(linearLayout); read.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { editText2.setText(read()); } }); write.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { write(editText1.getText().toString()); editText1.setText(""); } }); } private String read(){ //SD卡讀 try{ //如果手機插入SD卡,而且應用程式具有訪問sd卡的許可權 if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //獲取sd卡對應的儲存目錄 File sdCardDir=Environment.getExternalStorageDirectory(); //獲取指定檔案的輸入流 FileInputStream fis=new FileInputStream(sdCardDir.getCanonicalPath()+FILE_NAME); //將指定的輸入流包裝成BBufferedReader BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(fis)); StringBuilder builder=new StringBuilder(""); String line=null; while ((line=bufferedReader.readLine())!=null){ builder.append(line); } bufferedReader.close(); return builder.toString(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private void write(String content) { //SD卡寫 try{ //如果手機插入SD卡,而且應用程式具有訪問sd卡的許可權 if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //獲取sd卡對應的儲存目錄 Toast.makeText(FileActivity.this,"有許可權",Toast.LENGTH_SHORT).show(); File sdCardDir=Environment.getExternalStorageDirectory(); File targetFile=new File(sdCardDir.getCanonicalPath()+FILE_NAME); Toast.makeText(FileActivity.this,sdCardDir.getCanonicalPath()+FILE_NAME,Toast.LENGTH_SHORT).show(); //將指定檔案建立RandomAccessFile物件 //這裡使用RandomAccessFile向SD卡中指定追加內容,如果使用FileOutputStream向指定檔案寫資料會將原有的檔案內容清空,而不是追加的方式 RandomAccessFile raf=new RandomAccessFile(targetFile,"rw"); //將檔案的指標移動到最後面 raf.seek(targetFile.length()); //輸出檔案內容 raf.write(content.getBytes()); Toast.makeText(FileActivity.this,"完成",Toast.LENGTH_SHORT).show(); raf.close(); } } catch (IOException e) { e.printStackTrace(); } } }
例項:sd卡資料夾瀏覽器
(如果開發者不想用Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED),也可以使用/mnt/sdcard/路徑代表SD卡路徑
1、xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/path" android:textSize="20sp" android:layout_gravity="center_horizontal" android:layout_alignParentTop="true"/> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/list" android:divider="#000" android:dividerHeight="1px" android:layout_below="@+id/path"/> <Button android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/pzb" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:id="@+id/parent"/> </RelativeLayout>
2、activity
public class FileListActivity extends AppCompatActivity { ListView listView; TextView textView; //當前父目錄 File currentParent; File[] currentFiles; public void onCreate(Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.listfile_activity); listView=findViewById(R.id.list); textView=findViewById(R.id.path); //獲取系統的SD卡的目錄 File root=new File("/mnt/sdcard/"); //如果SD卡存在 if(root.exists()){ currentParent=root; currentFiles=root.listFiles(); //使用當前目錄下面的全部檔案,資料夾來填充listView inflateListView(currentFiles); } //為listview的列表的單擊事件繫結監聽器 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { //如果使用者點選檔案不是,直接返回,不做任何處理 if(currentFiles[i].isFile()) return ; //獲取使用者點選的資料夾下面的資料夾 File []tmp=currentFiles[i].listFiles(); if(tmp==null||tmp.length==0){ Toast.makeText(FileListActivity.this,"當前的路徑不可訪問,該路徑下面沒有檔案",Toast.LENGTH_SHORT).show(); }else { //獲取使用者單擊的列表項對應的資料夾,設當前的資料夾為父資料夾 currentParent=currentFiles[i]; //儲存當前點的父資料夾的全部內容 currentFiles=tmp; //再次更新ListView inflateListView(currentFiles); } } }); //獲取上一級目錄按鈕 Button parent=findViewById(R.id.parent); parent.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { if(!currentParent.getCanonicalPath().equals("/mnt/sdcard")){ //獲取上一級目錄 currentParent=currentParent.getParentFile(); //列出當前目錄下面的所有檔案 currentFiles=currentParent.listFiles(); //再次更新listView inflateListView(currentFiles); } } catch (IOException e) { e.printStackTrace(); } } }); } private void inflateListView(File[] files){ //建立一個list集合,list集合的元素是Map List<Map<String,Object>> list=new ArrayList<Map<String,Object>>(); for(int i=0;i<files.length;i++){ Map<String,Object> listItem=new HashMap<String,Object>(); //如果當前的file是檔案,使用folder圖示,否則使用file圖示 if(files[i].isDirectory()){ listItem.put("icon",R.drawable.p7txxw); } else{ listItem.put("icon",R.drawable.tp); } listItem.put("fileName",files[i].getName()); //新增list項 list.add(listItem); } SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.filelist_item,new String[]{"icon","fileName"},new int[]{R.id.file_image,R.id.file_name}); listView.setAdapter(adapter); try{ textView.setText("當前目錄:"+currentParent.getCanonicalPath()); } catch (IOException e) { e.printStackTrace(); } } }