【Android開發日記】之入門篇(七)——Android數據存儲(上)


在講解Android的數據源組件——ContentProvider之前我覺得很有必要先弄清楚Android的數據結構。
數據和程序是應用構成的兩個核心要素,數據存儲永遠是應用開發中最重要的主題之一,也是開發平台必須提供的基礎功能。不光是在Android平台上,在其他的平台上,數據的存儲永遠是不可缺少的一塊。Android的數據存儲是構建在Linux的文件系統上,它充分利用Linux的賬號系統來限定應用對數據的訪問,部署了一套安全和靈活並重的數據存儲解決方案。Android的文件框架,以及各種數據存儲手段,具體包括:Android的文件系統操作,設置文件的使用,數據庫的使用,數據源組件的使用以及雲端數據的存儲

一、Android的文件系統

  1. Android系統文件目錄
    目錄 內容
    system 系統目錄,放置在Android運行所需的核心庫
    data 應用目錄,放置着運行在Android上的應用及其數據
    sdcard 擴展存儲卡目錄,用來存放共享的數據
    mnt 記錄Android掛載的外部存儲信息








  2. Android的應用數據存儲機制
    在Android中,第三方應用及其數據,都存放在data目錄下。其中,應用安裝包會被存放到/data/app/目錄下,每個安裝包的文件名都形如:應用包名.apk,以避免重復。
    比如包名為com.test.sample的應用,其應用數據的目錄為/data/data/com.test.sample/。對應的數據庫文件存儲在/data/data/com.test.sample/database/目錄下,設置文件存儲在/data/data/com.test.sample/shared_prefs/,自定義的應用數據文件存儲在目錄/data/data/com.test.sample/files/下,等等。
    不僅如此,Android還會為每個應用創建一個賬號,只有通過本應用的賬號才有權限去運行該應用的安裝包文件,讀寫應用數據目錄下的文件(當然root權限除外啊~),從而保證了該應用數據不會再被其他應用獲取或破壞。
  3. Android的文件操作
    從應用數據目錄下可以看出數據文件可以分成兩類,一類是放置在擴展存儲器中的文件,即/sdcard/目錄下的文件,它們可以被各個應用共享;而另一類則是放在該應用數據目錄下文件,它們僅能被各個應用獨享,不能被其他應用讀寫。
    (1)擴展存儲器中的文件讀寫方式跟標准的java文件處理無異。
          
    我們可以新建一個FileUtil的工具類來幫助我們處理文件的I/O操作,首先我們先判斷SD卡的狀態,看看SD卡是否可用,還有多少可用容量等。新建一個FileUtil的Class,加入方法
     1 // =================get SDCard information===================
     2     public static boolean isSdcardAvailable() {
     3         String status = Environment.getExternalStorageState();
     4         //Environment.MEDIA_MOUNTED表示SD卡正常掛載
     5         if (status.equals(Environment.MEDIA_MOUNTED)) {
     6             return true;
     7         }
     8         return false;
     9     }
    10 
    11     public static long getSDAllSizeKB() {
    12         //sd卡的位置
    13         File path = Environment.getExternalStorageDirectory();
    14         //StatFs獲取的都是以block為單位的
    15         StatFs sf = new StatFs(path.getPath());
    16         // 得到單個block的大小
    17         long blockSize = sf.getBlockSize();
    18         // 獲取所有數據塊數
    19         long allBlocks = sf.getBlockCount();
    20         // 返回SD卡大小
    21         return (allBlocks * blockSize) / 1024; // KB
    22     }
    23 
    24     /**
    25      * free size for normal application
    26      * @return
    27      */
    28     public static long getSDAvalibleSizeKB() {
    29         File path = Environment.getExternalStorageDirectory();
    30         StatFs sf = new StatFs(path.getPath());
    31         long blockSize = sf.getBlockSize();
    32         long avaliableSize = sf.getAvailableBlocks();
    33         return (avaliableSize * blockSize) / 1024;// KB
    34     }

    Environment.getExternalStorageDirectory()表示獲取擴展存儲器的目錄。(建議使用此方法動態獲取,因為sdcard這個目錄路徑是可配置的)
    StatFs.getBlockSize在API18后變為StatFs.getBlockSizeLong,其他類似的getBlock方法也一樣,關於StatFs,詳情可以看這篇博文
    然后在activity中的button1加入事件

    case R.id.button1: {
                Log.d("TEST", "sdcard?"+FileUtil.isSdcardAvailable());
                Log.d("TEST", "全部容量"+(float)FileUtil.getSDAllSizeKB()/1024/1024);
                Log.d("TEST", "可用容量"+(float)FileUtil.getSDAvalibleSizeKB()/1024/1024);
                Toast.makeText(this, "status", Toast.LENGTH_SHORT).show();
                break;
            }

    運行結果如下

    接下來我們來判斷某個文件夾是否存在在SD卡中以及創建一個文件夾

    /**
         * @param director 文件夾名稱
         * @return
         */
        public static boolean isFileExist(String director) {
            File file = new File(Environment.getExternalStorageDirectory()
                    + File.separator + director);
            return file.exists();
        }
    
        /**
         * create multiple director
         * @param path
         * @return
         */
        public static boolean createFile(String director) {
            if (isFileExist(director)) {
                return true;
            } else {
                File file = new File(Environment.getExternalStorageDirectory()
                        + File.separator + director);
                if (!file.mkdirs()) {
                    return false;
                }
                return true;
            }
        }

    其中File.separator是表示分隔符,在不同操作系統下是不同的,如windows就是代表"/",而在Linux下卻是代表"\"。所以介意使用File.separator來代替分隔符。File.mkdirs()表示創建一個文件夾,且可附帶創建父目錄,而mkdir()不行,詳情的File大家可以查看官方文檔,或者看看這篇博文
    然后在activity中的button2加入響應事件

    case R.id.button2: {
                Log.d("TEST", "example文件夾存在?"+FileUtil.isFileExist("example"));
                Log.d("TEST", "創建forexample文件夾"+FileUtil.createFile("forexample"));
                Toast.makeText(this, "IsFile", Toast.LENGTH_SHORT).show();
                break;
            }  

    運行后可以看到

    我們會發現在手機的sdcard目錄下新建了一個forexample的文件夾

    最后我們來實現文件的讀和寫
    寫:

    /**
         * 
         * @param director
         *            (you don't need to begin with
         *            Environment.getExternalStorageDirectory()+File.separator)
         * @param fileName
         * @param content
         * @param encoding
         *            (UTF-8...)
         * @param isAppend
         *            : Context.MODE_APPEND
         * @return
         */
        public static File writeToSDCardFile(String directory, String fileName,
                String content, String encoding, boolean isAppend) {
            // mobile SD card path +path
            File file = null;
            OutputStream os = null;
            try {
                if (!createFile(directory)) {
                    return file;
                }
                file = new File(Environment.getExternalStorageDirectory()
                        + File.separator + directory + File.separator + fileName);
                os = new FileOutputStream(file, isAppend);
                if (encoding.equals("")) {
                    os.write(content.getBytes());
                } else {
                    os.write(content.getBytes(encoding));
                }
                os.flush();
            } catch (IOException e) {
                Log.e("FileUtil", "writeToSDCardFile:" + e.getMessage());
            } finally {
                try {
                    if (os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return file;
        }
    
        /**
         * write data from inputstream to SDCard
         */
        public File writeToSDCardFromInput(String directory, String fileName,
                InputStream input) {
            File file = null;
            OutputStream os = null;
            try {
                if (createFile(directory)) {
                    return file;
                }
                file = new File(Environment.getExternalStorageDirectory()
                        + File.separator + directory + File.separator + fileName);
                os = new FileOutputStream(file);
                byte[] data = new byte[bufferd];
                int length = -1;
                while ((length = input.read(data)) != -1) {
                    os.write(data, 0, length);
                }
                // clear cache
                os.flush();
            } catch (Exception e) {
                Log.e("FileUtil", "" + e.getMessage());
                e.printStackTrace();
            } finally {
                try {
                    os.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return file;
        }

    從上面可以看到有兩種寫入的方法,一種是將字符串直接寫入,另一種是將數據流寫到文件中。還有一點要提的是file的默認目錄就是sdcard的目錄,所以開頭不必每次都要加sdcard的目錄路徑。
    FileOutputStream(file, isAppend) 兩個參數,左邊是File文件,而右邊是一個boolean值,為true時,數據將會接在原來文件的后面寫入,而false是則會覆蓋。
    讀:

    public static String ReadFromSDCardFile(String directory,String fileName){
            String res=""; 
            File file = null;
            file = new File(Environment.getExternalStorageDirectory()
                    + File.separator + directory + File.separator + fileName);
            try {
                FileInputStream fis = new FileInputStream(file);
                int length = fis.available();
                byte [] buffer = new byte[length]; 
                fis.read(buffer);
    //將字節按照編碼格式轉成字符串 res
    = EncodingUtils.getString(buffer, "UTF-8"); fis.close(); return res; }catch (FileNotFoundException e) { // TODO Auto-generated catch block Log.d("TEST", "FileNotFound"); e.printStackTrace(); }catch (Exception e) { Log.d("TEST", "Can Not Open File"); e.printStackTrace(); } return null; }

    編碼默認是UTF-8,若是想要改變的話,將其作為參數傳入就行。
    Activity中在按鈕中加入響應

    case R.id.button3: {
                FileUtil.writeToSDCardFile("forexample", "test.txt",   
                        editText.getText().toString(), "UTF-8", true);
                Toast.makeText(this, "WriteFile", Toast.LENGTH_SHORT).show();
                break;
            } 
            case R.id.button4: {
                textView.setText(FileUtil.ReadFromSDCardFile("forexample", "test.txt"));
                Toast.makeText(this, "ReadFile", Toast.LENGTH_SHORT).show();
                break;
            }

    在文字編輯框上寫入“我是cpacm”,先點擊writefile按鈕,再點擊ReadFile,得到運行結果

    同時在根目錄下的forexample文件夾里會找到test.txt,里面有着“我是cpacm”的一行字。到此,文件的讀寫成功。
    (2)放在該應用數據目錄下的文件讀寫
         存儲在應用目錄下的私有數據目錄,通常不會通過File類的方式直接讀寫,而是利用一些封裝過的類或函數來操作。一般可以通過Context.openFileOutput來執行。
        在Activity加入兩個方法,分別為文件的讀和寫

        public void writeFile(String fileName,String writestr){ 
            try{ 
                    FileOutputStream fout =openFileOutput(fileName,MODE_PRIVATE); 
                    byte [] bytes = writestr.getBytes(); 
                    fout.write(bytes); 
                    fout.close(); 
                  } 
                    catch(Exception e){ 
                    e.printStackTrace(); 
                   } 
            } 
    
            //讀數據
        public String readFile(String fileName){ 
          String res=""; 
          try{ 
                 FileInputStream fin = openFileInput(fileName); 
                 int length = fin.available(); 
                 byte [] buffer = new byte[length]; 
                 fin.read(buffer);     
                 res = EncodingUtils.getString(buffer, "UTF-8"); 
                 fin.close();     
             } 
             catch(Exception e){ 
                 e.printStackTrace(); 
             } 
             return res; 
        }

    同時在按鈕的響應中加入

    case R.id.button5: {
                writeFile("test2.txt",editText.getText().toString());
                Toast.makeText(this, "WritePrivateFile", Toast.LENGTH_SHORT).show();
                break;
            } 
            case R.id.button6: {
                textView.setText(readFile("test2.txt"));
                Toast.makeText(this, "ReadPrivateFile", Toast.LENGTH_SHORT).show();
                break;
            }

    效果圖跟上張一樣。

    最后不要忘記在配置文件中聲明權限

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

二、Android設置文件的使用

用戶在使用應用時,常常會有一些個人偏好。為了滿足不同用戶的需求,應用通常會提供對應的設置項(Preference),讓用戶根據自己的喜好選擇。這些設置信息會存儲在本地並進行結構化地展示,使用戶可以編輯。

  1. 設置文件的存儲和使用

    Android應用的設置數據,可以通過android.content.SharedPreferences類來表示。它提供了一組數據讀取的接口,可以從設置文件中讀取給定鍵值的整形數,布爾型數等數據。
    首先是獲取SharedPreferences
    private SharedPreferences userInfo;
            //在界面組件或服務組件中調用,構造應用默認的設置文件,默認文件名字為_preferences.xml
            //userInfo = PreferenceManager.getDefaultSharedPreferences(this);  
            //或獲取指定名字的SharedPreferences對象  參數分別為存儲的文件名和存儲模式。
            userInfo = getSharedPreferences("preferences", Activity.MODE_PRIVATE); 
            
            //讀取數據,如果無法找到則會使用默認值
            String username = userInfo.getString("name", "未定義姓名");  
            String msg = userInfo.getString("msg", "未定義信息");
            //顯示文本
            textView.setText(username+","+msg);

    兩種獲取方式,默認或者指定一個文件
    接下來加入響應按鈕

            case R.id.button7: {
                //獲得SharedPreferences的編輯器
                SharedPreferences.Editor editor = userInfo.edit();
                //將信息存入相應的鍵值中
                editor.putString("name", editText.getText().toString()).commit();
                Toast.makeText(this, "SetName", Toast.LENGTH_SHORT).show();
                break;
            } 
            case R.id.button8: {
                //獲得SharedPreferences的編輯器
                SharedPreferences.Editor editor = userInfo.edit();
                //將信息存入相應的鍵值中ss
                editor.putString("msg", editText.getText().toString()).commit();
                Toast.makeText(this, "SetMessage", Toast.LENGTH_SHORT).show();
                break;
            } 
            case R.id.button9: {
    //獲得SharedPreferences文件 userInfo
    = getSharedPreferences("preferences", Activity.MODE_PRIVATE); String username = userInfo.getString("name", "未定義姓名"); String msg = userInfo.getString("msg", "未定義信息"); textView.setText(username+","+msg); Toast.makeText(this, "ShowMsg", Toast.LENGTH_SHORT).show(); break; } case R.id.button10: {
    //輸出XML文件 textView.setText(print()); Toast.makeText(
    this, "ShowXML", Toast.LENGTH_SHORT).show(); break; }

    按鈕7,8可以設置信息,按鈕9則從SharedPreferences文件中讀取信息並顯示在文字框中。按鈕10會顯示這個XML文件中的所有信息。


    訪問其他應用中的Preference(在SecondApp中訪問FirstApp的數據),前提條件是:FirstApp的preference創建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE權限。

    如:在<package name>為com.first.app的應用使用下面語句創建了preference("first_app_perferences")。

    Java代碼
    getSharedPreferences("first_app_perferences", Context.MODE_WORLD_READABLE);  

    在SecondApp中要訪問FirstApp應用中的preference,首先需要創建FirstApp應用的Context,然后通過Context 訪問preference ,訪問preference時會在應用所在包下的shared_prefs目錄找到preference

    Context firstAppContext = createPackageContext("com.first.app", Context.CONTEXT_IGNORE_SECURITY);   
    SharedPreferences sharedPreferences = firstAppContext.getSharedPreferences("first_app_perferences",  Context.MODE_WORLD_READABLE);   
    String name = sharedPreferences.getString("name", "");  
    int age = sharedPreferences.getInt("age", 0); 

    如果不通過創建Context訪問FirstApp應用的preference,可以以讀取xml文件方式直接訪問FirstApp應用的preference對應的xml文件,

    如: 
    File xmlFile = new File(“/data/data/<package name>/shared_prefs/first_app_perferences.xml”);//<package name>應替換成應用的包名: com.first.app

     

  2. 設置界面組件
    有一類特殊的Preference對象:android.preference.PreferenceGroup。它是容器型的Preference對象,負責管理一組相關聯的Preference對象。設置項編輯的界面組件,通常派生自android.preference.PreferenceActivity類。它可以將一個定制好的設置樹轉換成對應的控件呈現出來。
    public class PreferencesDemo extends PreferenceActivity{
         @Override
         public void onCreate(Bundle savadInstanceState){
             super.onCreate(savadInstanceState);
             this.addPreferencesFromResource(R.xml.preference);
         }
    }

    其中,R.xml.preference表示描述設置信息的資源文件。放在XML資源目錄下。
    詳細可以參考Android的配置界面PreferenceActivity

 
  1 public class MainActivity extends Activity implements OnClickListener {
  2     
  3      /** 存儲后的文件路徑:/data/data/<package name>/shares_prefs + 文件名.xml */ 
  4     public static final String PATH = "/data/data/com.example.datademo/shared_prefs/preferences.xml";
  5     private SharedPreferences userInfo;
  6 
  7     private Button button1;
  8     private Button button2;
  9     private Button button3;
 10     private Button button4;
 11     private Button button5;
 12     private Button button6;
 13     private Button button7;
 14     private Button button8;
 15     private Button button9;
 16     private Button button10;
 17     private TextView textView;
 18     private EditText editText;
 19 
 20     @Override
 21     protected void onCreate(Bundle savedInstanceState) {
 22         super.onCreate(savedInstanceState);
 23         setContentView(R.layout.activity_main);
 24 
 25         // 獲得界面的控件
 26         textView = (TextView) findViewById(R.id.textView1);
 27         editText = (EditText) findViewById(R.id.editText1);
 28         button1 = (Button) findViewById(R.id.button1);
 29         button1.setOnClickListener(this);
 30         button2 = (Button) findViewById(R.id.button2);
 31         button2.setOnClickListener(this);
 32         button3 = (Button) findViewById(R.id.button3);
 33         button3.setOnClickListener(this);
 34         button4 = (Button) findViewById(R.id.button4);
 35         button4.setOnClickListener(this);
 36         button5 = (Button) findViewById(R.id.button5);
 37         button5.setOnClickListener(this);
 38         button6 = (Button) findViewById(R.id.button6);
 39         button6.setOnClickListener(this);
 40         button7 = (Button) findViewById(R.id.button7);
 41         button7.setOnClickListener(this);
 42         button8 = (Button) findViewById(R.id.button8);
 43         button8.setOnClickListener(this);
 44         button9 = (Button) findViewById(R.id.button9);
 45         button9.setOnClickListener(this);
 46         button10 = (Button) findViewById(R.id.button10);
 47         button10.setOnClickListener(this);
 48         
 49         //在界面組件或服務組件中調用,構造應用默認的設置文件,默認文件名字為_preferences.xml
 50         //userInfo = PreferenceManager.getDefaultSharedPreferences(this);  
 51         //或獲取指定名字的SharedPreferences對象  參數分別為存儲的文件名和存儲模式。
 52         userInfo = getSharedPreferences("preferences.xml", Activity.MODE_PRIVATE); 
 53         
 54         //讀取數據,如果無法找到則會使用默認值
 55         String username = userInfo.getString("name", "未定義姓名");  
 56         String msg = userInfo.getString("msg", "未定義信息");
 57         //顯示文本
 58         textView.setText(username+","+msg);
 59     }
 60 
 61     @Override
 62     public void onClick(View v) {
 63         // TODO Auto-generated method stub
 64         switch (v.getId()) {
 65         case R.id.button1: {
 66             Log.d("TEST", "sdcard?"+FileUtil.isSdcardAvailable());
 67             Log.d("TEST", "全部容量"+(float)FileUtil.getSDAllSizeKB()/1024/1024);
 68             Log.d("TEST", "可用容量"+(float)FileUtil.getSDAvalibleSizeKB()/1024/1024);
 69             Toast.makeText(this, "status", Toast.LENGTH_SHORT).show();
 70             break;
 71         }
 72         case R.id.button2: {
 73             Log.d("TEST", "example文件夾存在?"+FileUtil.isFileExist("example"));
 74             Log.d("TEST", "創建forexample文件夾"+FileUtil.createFile("forexample"));
 75             Toast.makeText(this, "IsFile", Toast.LENGTH_SHORT).show();
 76             break;
 77         }  
 78         case R.id.button3: {
 79             FileUtil.writeToSDCardFile("forexample", "test.txt",   
 80                     editText.getText().toString(), "UTF-8", true);
 81             Toast.makeText(this, "WriteFile", Toast.LENGTH_SHORT).show();
 82             break;
 83         } 
 84         case R.id.button4: {
 85             textView.setText(FileUtil.ReadFromSDCardFile("forexample", "test.txt"));
 86             Toast.makeText(this, "ReadFile", Toast.LENGTH_SHORT).show();
 87             break;
 88         } 
 89         case R.id.button5: {
 90             writeFile("test2.txt",editText.getText().toString());
 91             Toast.makeText(this, "WritePrivateFile", Toast.LENGTH_SHORT).show();
 92             break;
 93         } 
 94         case R.id.button6: {
 95             textView.setText(readFile("test2.txt"));
 96             Toast.makeText(this, "ReadPrivateFile", Toast.LENGTH_SHORT).show();
 97             break;
 98         } 
 99         case R.id.button7: {
100             //獲得SharedPreferences的編輯器
101             SharedPreferences.Editor editor = userInfo.edit();
102             //將信息存入相應的鍵值中
103             editor.putString("name", editText.getText().toString()).commit();
104             Toast.makeText(this, "SetName", Toast.LENGTH_SHORT).show();
105             break;
106         } 
107         case R.id.button8: {
108             //獲得SharedPreferences的編輯器
109             SharedPreferences.Editor editor = userInfo.edit();
110             //將信息存入相應的鍵值中ss
111             editor.putString("msg", editText.getText().toString()).commit();
112             Toast.makeText(this, "SetMessage", Toast.LENGTH_SHORT).show();
113             break;
114         } 
115         case R.id.button9: {
116             userInfo = getSharedPreferences("preferences.xml", Activity.MODE_PRIVATE);
117             String username = userInfo.getString("name", "未定義姓名");  
118             String msg = userInfo.getString("msg", "未定義信息");
119             textView.setText(username+","+msg);
120             Toast.makeText(this, "ShowMsg", Toast.LENGTH_SHORT).show();
121             break;
122         } 
123         case R.id.button10: {
124             textView.setText(print());
125             Toast.makeText(this, "ShowXML", Toast.LENGTH_SHORT).show();
126             break;
127         } 
128         }
129     }
130     
131     public void writeFile(String fileName,String writestr){ 
132         try{ 
133                 FileOutputStream fout =openFileOutput(fileName,MODE_PRIVATE); 
134                 byte [] bytes = writestr.getBytes(); 
135                 fout.write(bytes); 
136                 fout.close(); 
137               } 
138                 catch(Exception e){ 
139                 e.printStackTrace(); 
140                } 
141         } 
142 
143         //讀數據
144     public String readFile(String fileName){ 
145       String res=""; 
146       try{ 
147              FileInputStream fin = openFileInput(fileName); 
148              int length = fin.available(); 
149              byte [] buffer = new byte[length]; 
150              fin.read(buffer);     
151              res = EncodingUtils.getString(buffer, "UTF-8"); 
152              fin.close();     
153          } 
154          catch(Exception e){ 
155              e.printStackTrace(); 
156          } 
157          return res; 
158     }
159     
160     private String print() {  
161         StringBuffer buff = new StringBuffer();  
162         try {  
163             BufferedReader reader = new BufferedReader(new InputStreamReader(  
164                     new FileInputStream(PATH)));  
165             String str;  
166             while ((str = reader.readLine()) != null) {  
167                 buff.append(str + "/n");  
168             }  
169         } catch (Exception e) {  
170             e.printStackTrace();  
171         }  
172         return buff.toString();  
173     }
174 
175 }
View Code
  1 package com.example.datademo;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FileNotFoundException;
  6 import java.io.FileOutputStream;
  7 import java.io.IOException;
  8 import java.io.InputStream;
  9 import java.io.OutputStream;
 10 
 11 import org.apache.http.util.EncodingUtils;
 12 
 13 import android.os.Environment;
 14 import android.os.StatFs;
 15 import android.util.Log;
 16 
 17 public class FileUtil {
 18     private static int bufferd = 1024;
 19 
 20     private FileUtil() {
 21     }
 22 
 23     /*
 24      * <!-- 在SDCard中創建與刪除文件權限 --> <uses-permission
 25      * android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!--
 26      * 往SDCard寫入數據權限 --> <uses-permission
 27      * android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 28      */
 29 
 30     // =================get SDCard information===================
 31     public static boolean isSdcardAvailable() {
 32         String status = Environment.getExternalStorageState();
 33         //Environment.MEDIA_MOUNTED表示SD卡正常掛載
 34         //sd卡   http://blog.csdn.net/yuzhiboyi/article/details/8645730
 35         if (status.equals(Environment.MEDIA_MOUNTED)) {
 36             return true;
 37         }
 38         return false;
 39     }
 40 
 41     public static long getSDAllSizeKB() {
 42         // get path of sdcard
 43         File path = Environment.getExternalStorageDirectory();
 44         //StatFs獲取的都是以block為單位的   http://blog.csdn.net/pang3510726681/article/details/6969557
 45         StatFs sf = new StatFs(path.getPath());
 46         // get single block size(Byte)
 47         long blockSize = sf.getBlockSize();
 48         // 獲取所有數據塊數
 49         long allBlocks = sf.getBlockCount();
 50         // 返回SD卡大小
 51         return (allBlocks * blockSize) / 1024; // KB
 52     }
 53 
 54     /**
 55      * free size for normal application
 56      * 
 57      * @return
 58      */
 59     public static long getSDAvalibleSizeKB() {
 60         File path = Environment.getExternalStorageDirectory();
 61         StatFs sf = new StatFs(path.getPath());
 62         long blockSize = sf.getBlockSize();
 63         long avaliableSize = sf.getAvailableBlocks();
 64         return (avaliableSize * blockSize) / 1024;// KB
 65     }
 66 
 67     // =====================File Operation==========================
 68     /**
 69      * @param director 文件夾名稱
 70      * @return
 71      */
 72     public static boolean isFileExist(String director) {
 73         File file = new File(Environment.getExternalStorageDirectory()
 74                 + File.separator + director);
 75         return file.exists();
 76     }
 77 
 78     /**
 79      * create multiple director
 80      * 
 81      * @param path
 82      * @return
 83      */
 84     public static boolean createFile(String director) {
 85         if (isFileExist(director)) {
 86             return true;
 87         } else {
 88             File file = new File(Environment.getExternalStorageDirectory()
 89                     + File.separator + director);
 90             if (!file.mkdirs()) {
 91                 return false;
 92             }
 93             return true;
 94         }
 95     }
 96 
 97     public static File writeToSDCardFile(String directory, String fileName,
 98             String content, boolean isAppend) {
 99         return writeToSDCardFile(directory, fileName, content, "", isAppend);
100     }
101 
102     /**
103      * 
104      * @param director
105      *            (you don't need to begin with
106      *            Environment.getExternalStorageDirectory()+File.separator)
107      * @param fileName
108      * @param content
109      * @param encoding
110      *            (UTF-8...)
111      * @param isAppend
112      *            : Context.MODE_APPEND
113      * @return
114      */
115     public static File writeToSDCardFile(String directory, String fileName,
116             String content, String encoding, boolean isAppend) {
117         // mobile SD card path +path
118         File file = null;
119         OutputStream os = null;
120         try {
121             if (!createFile(directory)) {
122                 return file;
123             }
124             file = new File(Environment.getExternalStorageDirectory()
125                     + File.separator + directory + File.separator + fileName);
126             os = new FileOutputStream(file, isAppend);
127             if (encoding.equals("")) {
128                 os.write(content.getBytes());
129             } else {
130                 os.write(content.getBytes(encoding));
131             }
132             os.flush();
133         } catch (IOException e) {
134             Log.e("FileUtil", "writeToSDCardFile:" + e.getMessage());
135         } finally {
136             try {
137                 if (os != null) {
138                     os.close();
139                 }
140             } catch (IOException e) {
141                 e.printStackTrace();
142             }
143         }
144         return file;
145     }
146 
147     /**
148      * write data from inputstream to SDCard
149      */
150     public static File writeToSDCardFromInput(String directory, String fileName,
151             InputStream input) {
152         File file = null;
153         OutputStream os = null;
154         try {
155             if (createFile(directory)) {
156                 return file;
157             }
158             file = new File(Environment.getExternalStorageDirectory()
159                     + File.separator + directory + File.separator + fileName);
160             os = new FileOutputStream(file);
161             byte[] data = new byte[bufferd];
162             int length = -1;
163             while ((length = input.read(data)) != -1) {
164                 os.write(data, 0, length);
165             }
166             // clear cache
167             os.flush();
168         } catch (Exception e) {
169             Log.e("FileUtil", "" + e.getMessage());
170             e.printStackTrace();
171         } finally {
172             try {
173                 os.close();
174             } catch (Exception e) {
175                 e.printStackTrace();
176             }
177         }
178         return file;
179     }
180     
181     public static String ReadFromSDCardFile(String directory,String fileName){
182         String res=""; 
183         File file = null;
184         file = new File(Environment.getExternalStorageDirectory()
185                 + File.separator + directory + File.separator + fileName);
186         try {
187             FileInputStream fis = new FileInputStream(file);
188             int length = fis.available();
189             byte [] buffer = new byte[length]; 
190             fis.read(buffer);
191             res = EncodingUtils.getString(buffer, "UTF-8");
192             fis.close();
193             return res;
194         }catch (FileNotFoundException  e) {
195             // TODO Auto-generated catch block
196             Log.d("TEST", "FileNotFound");
197             e.printStackTrace();
198         }catch (Exception  e) {
199             Log.d("TEST", "Can Not Open File");
200             e.printStackTrace();
201         }
202         return null;     
203     }
204 }
View Code

資源下載:DataDemo

參考文章:(1)Android中的SharedPreferences存儲數據方式  http://blog.csdn.net/zuolongsnail/article/details/6556703
         (2)Android - 文件操作 小結   http://www.open-open.com/lib/view/open1330957864280.html
限於篇幅,這篇文章就到此結束,這篇主要講了如何在Android中讀寫文件,包括SDCard中和應用內部的文件。以及如何使用設置文件。在下一篇我會講解Android內部自帶的數據庫使用及操作。

========================================

作者:cpacm
出處:(http://www.cpacm.net/2015/03/22/Android開發日記(五)——Android數據存儲(上)/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM