Android开发技术之文件的简单存储—小白篇(二)

来源:互联网 发布:淘宝天猫运营提成方案 编辑:程序博客网 时间:2024/05/18 00:48
        近期忙于一个市级赛项,由于比赛需要,所以这两天对android的文件存储进行了一个初步了解。现贴上这两天的学习内容,供新手小白参考,若有不懂或迷惑的地方,可联系本人QQ1101326120

一:手机内部存储空间文件的读取;

        1.使用该种方式存储文件,首先要获取本应用程序的数据文件夹,android为我们提供了openFileOutput(String name,int mode)和openFileInput(String name)来获取。查看帮助文档可见

         其中openFileOutput(String name,int mode)的返回类型为FileOutputStream,即使用该方法创建一个文件输出流,用来向文件中写入数据。其中第一个参数String为文件名,第二个int型参数mode有以下四个值:

        Context.MODE_PRIVATE:                                          默认模式,表示私有数据;

        Context.MODE_APPEND:                                         检查文件是否存在,如果存在会往文件追加内容,否则创建文件再写入;

        Context.MODE_WORLD_READABLE:                   当前文件可以被其他应用读取;

        Context.MODE_WORLD_WRITEABLE:                 当前文件可以被其他文件写入。

以上四个值,除了MODE_APPEND会将内容追加到文件末尾,其他的都会覆盖掉原文件内容。如果需要使用多个值可以这样使用:Context.MODE_PRIVATE+Context.MODE_APPEND;

        openFileInput(String name)的返回类型为FileInputStream,即使用该方法创建一个文件输入流,用来读取数据。其中参数String为需要读取的文件名,FileOutputStream和FileInputStream为java API中IO包里面的一个类,其中有这样一段注释:

         也就是说这个类用于处理字节流的文件有较好的性能,却也不是不可以用来处理字符,下面是用该类中的方法来处理字符的代码:

         方法一:

protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);save=(TextView)findViewById(R.id.save);open=(TextView)findViewById(R.id.open);edit=(EditText)findViewById(R.id.edit);edit2=(EditText)findViewById(R.id.edit2);save.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubwrite(edit.getText().toString());edit.setText("");Toast.makeText(getApplicationContext(), "写入成功!", Toast.LENGTH_SHORT).show();}});open.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubedit2.setText(read());}});}public void write(String content){                               //传入StringFileOutputStream output;try {output = openFileOutput("aaa",Context.MODE_WORLD_READABLE);       //用可读模式创建文件byte[] by=content.getBytes();       //因为FileOutputStream用来处理字节,所以要将传入的String转换为字节型          output.write(by);                   //向文件里面写入数据output.flush();                     //刷新文件流output.close();                     //关闭流释放资源} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public String read(){FileInputStream input = null;String str ="";       try {input = openFileInput("aaa");                          //从指定文件获得字节/*使用下边注释中的代码时无法完整读取数据                                                 *还会有乱码现象发生                                                 *估计是读取过程中发生了阻塞*/                                                //int lenth=input.toString().length();    //因为在使用read方法时需要指定字节的长度,所以我们提前获取数据的长度//byte[] by=new byte[lenth];              //字节大小为数据的长度                        int lenth=input.available();              //该方法专门用来处理上述问题                                                input.read(lenth);                         //和上面write方法一样,用来处理字节                        str=new String(by,"UTF-8"); //因为最终给文本设置的类型为string型,所以我们还需要通过utf-8编码将by转换为字符型                        input.close();                          //关闭流释放内存} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return str;                                                //该返回的str即转型后的by}
        以上操作结果可以在设备内存date/date/包名/file/文件夹中查看,若是真机调试,必须要有root权限。

       前文中已经提到过FileOutputStream和FileInputStream用于处理字节,所以如果要较好地处理字符数据就得要将字节转换为字符类型,正好java api提供为我们提供了InputStreamReaderOutputStreamWriter用于处理该类问题,查看api可见:

代码如下:

方法二:

public void write(String content){                               //传入Stringtry {FileOutputStream output = openFileOutput("aaa",Context.MODE_WORLD_READABLE);    //用可读模式创建文件(字节流)BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(output,"UTF-8"));       //该处先将字符数据添加缓存功能后再存入字节流                        writer.write(content);                                           //写入数据                        writer.flush();                        writer.close();} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public String read(){String str ="";        try {    String string=null;            FileInputStream input = openFileInput("aaa");                                 //从指定文件获得字节            BufferedReader buffer=new BufferedReader(new InputStreamReader(input,"UTF-8"));       //将字节流转换为字符流并为其添加缓存功能                     while((string=buffer.readLine())!=null){                  //判断读取数据是否为空,若不判断程序就无法处理,会报错闪退    String ch=buffer.readLine();                            //或许readLine是该类中最有用的一个方法,事实证明确实如此                str=new String(ch);                buffer.close();    }}catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return str;                                                //该返回的str即转型后的by}

         上述方法是将字节流和字符流互相转换后进行数据读取,并为其添加了缓存功能,当然如果不用缓存功能也可以,将它们进行转换后直接进行读取。另外,java API中还为我们提供了一些方法可以达到类似效果,我们可以使用字节缓冲类BufferedOutputStream和BufferedInputStream实现缓冲功能,具体功能,api注释可见:

根据本人理解,缓存功能其实是先将数据装进一个数组,然后每次对数组内的数据进行修改,直到最后确定保存时才将数据写入文件,避免了对内存文件的频繁调用,以下为实现代码:

方法三:

public void write(String content){                               //传入Stringtry {FileOutputStream output = openFileOutput("aaa",Context.MODE_WORLD_READABLE);BufferedOutputStream buffer=new BufferedOutputStream(output);              //为其实现缓冲功能byte[] by=content.getBytes();buffer.write(by);                       //write返回类型为voidbuffer.flush();buffer.close();}catch (FileNotFoundException e) {// TODO Auto-generated catch block        e.printStackTrace();}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public String read(){String str = null;try {      FileInputStream input = openFileInput("aaa");      BufferedInputStream buffer=new BufferedInputStream(input);      byte[] by=new byte[buffer.available()];      input.read(by);            //参考api可见read返回类型为int,所以要获取字节长度      str=new String(by);      input.close();}catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();       }return str;                                                //该返回的str即转型后的by        }

其实我刚开始的想法是用API提供的FileReaderFileWriter中的方法来进行对手机内部存储文件的读取,或许有很多朋友和我这种想法一样。后来我试了很多次都无法实现这种效果,总结原因如下:

    1.android提供用来获取设备存储目录的方法为openFileOutput(String name,int mode)和openFileInput(String name),然而这两种方法的返回值是用来处理字节的文件流,分别为FileOutputStream和FileInputStream。FileReaderFileWriter为处理字符的文件流;

   2.常用的存储方式是关于字节的处理;


二:sd卡中文件的读取:

       原理和方式与设备内存文件的读取基本一样,只不过先要判断sd卡的状态,具体步骤与代码如下:

public void write(String content){                               //传入String                   if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){             //判断sd卡状态File file=Environment.getExternalStorageDirectory();                        //得到sd卡根目录File date=new File(file,"date");                                            //创建文件try {BufferedWriter writer =new BufferedWriter(new FileWriter(date));     //为字符流添加缓存writer.write(content);                                               //写入数据writer.flush();writer.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public String read(){    String str="";if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){try {File file=Environment.getExternalStorageDirectory();File date=new File(file,"date");BufferedReader reader=new BufferedReader(new FileReader(date));           //作用同上String string=null;while((string=reader.readLine())!=null){                                 //判断数据是否为空,如果不加判断,程序会报错闪退        str=new String(reader.readLine());                               //读取每行数据,它的返回值为string类型reader.close();}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return str;                                                //该返回的str即转型后的by}


3 0
原创粉丝点击