Android文件IO详解

首先让我们回顾一下JavaIO。看图:

这里写图片描述

看到这么多流,是不是头都大了,当年我学这块的时候,心想什么玩意,这流那流的。什么时候该用什么流?输入流和输出流经常弄混,不知道什么时候该用输出?什么时候该用输入?接下来看图 :

这里写图片描述

上面这张图说明了最基本的输入,输出。当然我们的数据源方向不一定只有文件,或许是内存或者网络。接下来说一下什么是字节流,字符流。

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

说白了节点流就是连接程序与数据源的一个管子,单纯的用来传送数据,并不对数据进行额外处理。而处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据的读写,如BufferedReader,。说白了处理流就是在管子外面又套了一层,对水进行了过滤或者消毒。对数据进行了额外的处理,增强了额外的传输功能。处理流的构造方法总是要带一个其他的流对象做参数。
常用的节点流
父 类 InputStream OutputStream Reader Writer
文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流
数 组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
字符串 StringReader StringWriter 对字符串进行处理的节点流
管 道 PipedInputStream PipedOutputStream PipedReader PipedWriter 对管道进行处理的节点流
常用处理流(关闭处理流使用关闭里面的节点流)
父 类 InputStream OutputStream Reader Writer
缓冲流 BufferedImputStrean BufferedOutputStream BufferedReader BufferedWriter —-需要父类作为参数构造,增加缓冲功能,避免频繁读写硬盘,可以初始化缓冲数据的大小,由于带了缓冲功能,所以就写数据的时候需要使用flush方法
转换流 InputStreamReader OutputStreamWriter- 要inputStream或OutputStream作为参数,实现从字节流到字符流的转换
数据流 DataInputStream DataOutputStream -提供将基础数据类型写入到文件中,或者读取出来,为什么要有这个流呢?看这样的分析,如果没有这种流的话,有一个long,本身只占8个字节,如果我要写入到文件,需要转成字符串,然后在转成字符数组,那空间会占用很多,但是有了这种流之后就很方便了,直接将这8个字节写到文件就完了。。是不是既节约了内存空间有让程序写起来更加方便简单了呐。写倒是很简单,但是读取的时候就注意了,根据读取的数据类型,指针会往下移,所以你写的顺序必须要和读的顺序一致才能完成你正确的需求。
Android中的IO其实就是javaIO,只不过在处理细节上增加了几个好用的方法。下面看例子:

这里写图片描述
这里写图片描述

主要代码:

@Override  
    public void onClick(View v) {  
        String name=mUserName.getText().toString();  
        String age=mAge.getText().toString();  
        String userInfo="用户名:"+name+";年龄:"+age+";性别:"+sexText+"\r\n";  
        int id=v.getId();  
        if(id==R.id.write_button){  
            try {  
                //1,此方法需要将字符串转换为字节写入文件  
                //MODE_APPEND:追加模式|MODE_WORLD_READABLE:全局可读|MODE_WORLD_WRITEABLE:全局可写  
                //FileOutputStream fos=this.openFileOutput("androidtoast.txt", MODE_APPEND|MODE_WORLD_READABLE|MODE_WORLD_WRITEABLE);  
                //fos.write(userInfo.getBytes());  
                //fos.close();  

                //2,以字符的形式直接写入文件  
                //得到Data目录      注:能操作文件夹只有两个地方:1.sdcard 2./data/data/<package_name>/  
                //File dir = Environment.getDataDirectory();//得到data目录  
                //File newFile=new File(dir,"/data/com.iteye.androidtoast/androidtoast.txt");  
                //FileWriter fw=new FileWriter(newFile,true);  
                //fw.write(userInfo);//直接将字符写入文件  
                //fw.close();  

                //3,以缓冲流的方式写入文件,这种方式能显著减少IO的次数,在操作大文本的时经常用  
                File dir = Environment.getDataDirectory();//得到data目录  
                File newFile=new File(dir,"/data/com.iteye.androidtoast/androidtoast.txt");  
                FileWriter fw=new FileWriter(newFile,true);//以追加的模式将字符写入  
                BufferedWriter bw=new BufferedWriter(fw);//又包裹一层缓冲流 增强IO功能  
                bw.write(userInfo);  
                bw.flush();//将内容一次性写入文件  
                bw.close();  
                Toast.makeText(this, "成功写入", 1).show();  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
                Toast.makeText(this, "文件没有找到", 1).show();  
            }catch (IOException e) {  
                e.printStackTrace();  
            }  

        }else if(id==R.id.read_button){  
            String content="";//读取到的内容  
            String temp = "";//存放内容  
            File dir = Environment.getDataDirectory();//得到data目录  
            File newFile=new File(dir,"/data/com.iteye.androidtoast/androidtoast.txt");  
            try {  
                FileReader fr=new FileReader(newFile);  
                BufferedReader br=new BufferedReader(fr);  
                //一行一行读取 。在电子书程序上经常会用到。  
                while((content=br.readLine())!=null){  
                    temp+=content+"\r\n";  
                }  
                mContent.setText(temp);  
                br.close();  
            } catch (FileNotFoundException e) {   
                e.printStackTrace();  
                Toast.makeText(this, "文件没有找到", 1).show();  
            } catch (IOException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
    }  

Android提供了几个操作文件输入输出的方法,这些方法封装了一些功能。如路径的构建,是否采用追加模式等等。
Context. openFileOutput(“androidtoast.txt”, MODE_APPEND|MODE_WORLD_READABLE|MODE_WORLD_WRITEABLE);
这个方法封装了输出流的创建,并提供了几种操作模式。首先通过这个方法打开输出流,系统会在
/data/data/下创建一个files文件夹。你所写入的数据存放在此。如果你的程序想支持外部程序也能对你的文件进行读写,需要加入|MODE_WORLD_READABLE|MODE_WORLD_WRITEABLE这两个操作模式。全局可读可写。注意:如果你的程序需要支持外部程序的读写,那么就只能用这种流操作方法。其他的流操作方法是不支持全局读写。

对SD卡得读写,我示例中没写。下面说一下,首先需要得到SD当前状态 然后判断是否挂载

//得到外存设备的状态
String state = Environment.getExternalStorageState();
//状态为已挂载
if(state.equals(Environment.MEDIA_MOUNTED)){
//得到sd卡的目录
File dir = Environment.getExternalStorageDirectory();
File newFile = new File(dir,”androidtoast.txt”);
FileOutputStream fos = new FileOutputStream(newFile,true);
fos.write(cont.getBytes());
fos.close();
}
注意 需要加入两个权限



转自:http://androidtoast.iteye.com/blog/1172673


最后,我自己的理解,仅供帮助自己记忆,对错不予负责:
无论这个流还是那个流,它们的本质就是字节数据的传输,只是也许需要考虑到以下几点:
1、反复多次的读取磁盘会比较耗时,所以要尽可能的减少读取磁盘的次数。比如用byte[]批量读取;比如用运用缓存数组(BufferedInputStream / BufferedOutputStream);等等。
2、单个字节的数据是没有任何意义的,只有当它以一定的格式组合起来才有意义。比如4个字节组成int;比如先输出两个字节来表示字符串的字节长度,再输出字符串的字节值,以这个组合来表示字符串(DataInputStream / DataOutputStream);比如一个对象就是一串被序列化过的字节组合(ObjectInputStream / ObjectOutputStream);等等。
3、编码的转换问题。一个字符用不同的编码方式表示会是不同的字节组合。java编码是unicode(双字节),android是utf-8(英文单字节,中文三字节),windows是GBK(英文单字节,中文双字节)。
4、接入的数据源不同。可以是外部磁盘的文件(FileInputStream / FileOutputStream),也可以是内存中的byte数组(ByteArrayInputStream / ByteArrayOutputStream)等。
附:

 //单字节读取标准格式
        FileInputStream fis = new FileInputStream("D:/test/a.txt");
        int b;
        while ((b = fis.read()) != -1) {
            System.out.println(b);
        }
        fis.close();
 //批量读取标准格式
        FileInputStream fis = new FileInputStream("D:/test/a.txt");
        int b;
        byte[] buf = new byte[3];
        while ((b = fis.read(buf)) != -1) {
            System.out.println(b+Arrays.toString(buf));
        }
        fis.close();
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值