首页 > 代码库 > Android数据存储(上)

Android数据存储(上)

数据和程序是应用构成的两个核心要素,数据存储永远是应用开发中最重要的主题之一,也是开发平台必须提供的基础功能。不光是在Android平台上,在其他的平台上,数据的存储永远是不可缺少的一块。Android的数据存储是构建在Linux的文件系统上,它充分利用Linux的账号系统来限定应用对数据的访问,部署了一套安全和灵活并重的数据存储解决方案。Android的文件框架,以及各种数据存储手段,具体包括:Android的文件系统操作,设置文件的使用,数据库的使用,数据源组件的使用以及云端数据的存储

一、Android的文件系统

  1. Android系统文件目录

 

目录内容
system系统目录,放置在Android运行所需的核心库
data应用目录,放置着运行在Android上的应用及其数据
sdcar扩展存储卡目录,用来存放共享的数据
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; // KB22     }23 24     /**25      * free size for normal application26      * @return27      */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;// KB34     }

 

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 = http://www.mamicode.com/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             //将信息存入相应的键值中ss111             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 }
  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 director105      *            (you don‘t need to begin with106      *            Environment.getExternalStorageDirectory()+File.separator)107      * @param fileName108      * @param content109      * @param encoding110      *            (UTF-8...)111      * @param isAppend112      *            : Context.MODE_APPEND113      * @return114      */115     public static File writeToSDCardFile(String directory, String fileName,116             String content, String encoding, boolean isAppend) {117         // mobile SD card path +path118         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 SDCard149      */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 = http://www.mamicode.com/new byte[bufferd];162             int length = -1;163             while ((length = input.read(data)) != -1) {164                 os.write(data, 0, length);165             }166             // clear cache167             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 block196             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 }

Android数据存储(上)