1. 程式人生 > >android的資料儲存(1)(SharedPreference、File)

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