黑马程序员技术交流社区

标题: IO字节流核心代码 [打印本页]

作者: 2406035442    时间: 2014-10-15 22:58
标题: IO字节流核心代码
###一.IO流
* 1.概念
        * IO流用来处理设备之间的数据传输
        * Java对数据的操作是通过流的方式
        * Java用于操作流的类都在IO包中
        * 流按流向分为两种:输入流,输出流。
        * 流按操作类型分为两种:
                * 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
                * 字符流 : 字符流只能操作纯字符数据,比较方便。
* 2.IO流常用父类
        * 字节流的抽象父类:
                * InputStream
                * OutputStream
        * 字符流的抽象父类:
                * Reader
                * Writer               
* 3.IO程序书写
        * 使用前,导入IO包中的类
        * 使用时,进行IO异常处理
        * 使用后,释放资源
###二.字节流
* 1.常用方法
        * InputStream:
                * read()                        读取一个字节
                * read(byte[])        读取若干(数组长度)字节
                * available()                获取可读的字节数
                * close()                        关闭流, 释放资源
        * OutputStream:
                * write(int)                写出一个字节
                * write(byte[])        写出数组中的所有字节
                * write(byte[],start,len);
                * close()                        关闭流, 释放资源
* 2.读取文件
        * 创建FileInputStream对象, 指定一个文件. 文件必须存在, 不存在则会抛出FileNotFoundException
        * 使用read()方法可以从文件中读取一个字节. 如果读取到文件末尾会读到-1
        * 读取结束后需要释放资源, 调用close()方法关闭输入流
*
                输入流代码
                FileInputStream fis = new FileInputStream("xxx.txt");                //创建流对象,关联xxx.txt文件
                int b;
                while((b = fis.read()) != -1) {                                                                //将每次读到的结果赋值给b
                        System.out.println(b);
                }
               
                fis.close();
        * 为什么read方法返回是int而不是byte类型呢?
                * 因为如果读取的是视频文件或音频文件或图片文件等,在读取过程中很有可能会遇到11111111,也就是byte类型的-1,那么遇到-1程序就会停止读取,会漏掉文件,为了防止这种情况出现,把byte类型提升为int类型,在这个字节前补上24个0,把遇到的-1变成255,这样可以保证将整个文件读完
* 3.写出文件
        * 创建FileOutputStream对象, 指定一个文件. 文件不存在会创建新文件, 存在则清空原内容. 如果需要追加, 在构造函数中传入true.
        * 使用write()方法可以向文件写出一个字节.
        * 写出结束后同样需要调用close()
*
                输出流代码
                FileOutputStream fos = new FileOutputStream("aaa.txt");        //创建流对象,关联aaa.txt
                fos.write(100);                                                                                        //写出数据的时候会将前面24个0去掉,写出的是一个字节
                fos.write(98);
                fos.write(99);
                fos.close();                                                                                        //关闭流,释放资源

* 4.拷贝文件
        * 可以从文件中逐个字节读取, 逐个字节写出, 但这样做效率非常低
        * 我们可以定义一个数组作为缓冲区, 一次读取多个字节装入数组, 然后再一次性把数组中的字节写出1byte = 8bit               
        * 1,逐个字节拷贝
                       
                        FileInputStream fis = new FileInputStream("致青春.mp3");                //创建输入流对象,关联致青春.mp3
                        FileOutputStream fos = new FileOutputStream("copy.mp3");        //创建输出流对象,关联copy.mp3
                       
                        int b;
                        while((b = fis.read()) != -1) {                                                                //将每次读到的赋值给b
                                fos.write(b);                                                                                        //将b中的字节写出去
                        }
                       
                        fis.close();                                                                                                //关流,释放资源
                        fos.close();  
        * 2,自定义数组拷贝               
                       
                        FileInputStream fis = new FileInputStream("致青春.mp3");                //创建输入流对象,关联致青春.mp3
                        FileOutputStream fos = new FileOutputStream("copy.mp3");        //创建输出流对象,关联copy.mp3
                        byte[] arr = new byte[1024 * 8];                                                        //自定义数组
                        int len;
                        while((len = fis.read(arr)) != -1) {                                                        //将数据读到字节数组中
                                fos.write(arr, 0, len);                                                                        //从字节数组中将数据写到文件上
                                //fos.write(arr);
                        }
                       
                        fis.close();                                                                                                //关流,释放资源
                        fos.close();
                       
                        int len = read(arr);如果文件上有数据返回的就是读到有效的字节个数,如果文件上没有数据返回的就是-1
        * 3,定义一个大数组拷贝,数组和文件的字节个数一样大
                       
                        //fis.available();一次获取读的文件的大小
                        FileInputStream fis = new FileInputStream("致青春.mp3");
                        FileOutputStream fos = new FileOutputStream("copy.mp3");
                        byte[] arr = new byte[fis.available()];                                                //虽然可以拷贝,但是在开发时不建议,有可能会导致内存溢出
                        fis.read(arr);
                        fos.write(arr);
                        fis.close();
        * 4,带缓冲区的拷贝
                       
                        FileInputStream fis = new FileInputStream("致青春.mp3");                //创建输入流对象,关联致青春.mp3
                        BufferedInputStream bis = new BufferedInputStream(fis);                //对fis进行包装,内置一个8192大小的字节数组               
                        FileOutputStream fos = new FileOutputStream("copy.mp3");        //创建输出流对象,关联copy.mp3
                        BufferedOutputStream bos = new BufferedOutputStream(fos);        //对fos进行包装,内置一个8192大小的字节数组
                       
                        int b;
                        while((b = bis.read()) != -1) {                                                                //read一次会先将文件上的数据读到缓冲区中,再从缓冲区一个一个的赋值给b
                                bos.write(b);                                                                                        //write一次,是将b中的字节数据写到缓冲区,缓冲区写满再一次写到文件上
                        }
                       
                        bis.close();                                                                                                //只需要关掉包装后的即可
                        bos.close();

* 5.BufferedInputStream
        * BufferedInputStream内置了一个缓冲区(数组)
        * 从BufferedInputStream中读取一个字节时
        * BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
        * 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
        * 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
* 6.BufferedOutputStream
        * BufferedOutputStream也内置了一个缓冲区(数组)
        * 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
        * 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
* 7.读中文
        * 字节流只读中文有弊端,可能会出现半个中文
        * 解决办法
        * 1,用字符流只读
        * 2,将文件上的所有的字节数据都读到缓冲区中,然后在转换成字符串ByteArrayOutputStream
*
                FileInputStream fis = new FileInputStream("bbb.txt");
                byte[] arr = new byte[4];
                int len;
                while((len = fis.read(arr)) != -1) {
                        System.out.println(new String(arr,0,len));
                }
               
                fis.close();
* 8.写中文
        * 字节流是可以写字符串的
        * 但是必须将字符串转换成字节数组写出去
*
                 FileOutputStream fos = new FileOutputStream("bbb.txt");
                fos.write("你要减肥,造吗".getBytes());
                fos.close();
* 9.finally嵌套
* 1.6版本及以前的标准的异常处理代码
               
                FileInputStream fis = null;
                FileOutputStream fos = null;
                try {
                        fis = new FileInputStream("aaa.txt");
                        fos = new FileOutputStream("bbb.txt");
                       
                        int b;
                        while((b = fis.read()) != -1) {
                                fos.write(b);
                        }
                }finally {
                        try {
                                if(fis != null)
                                        fis.close();
                        } finally {
                                if(fos != null)
                                        fos.close();
                        }
                }
* 10.try close
* 1.7版本的标准的异常处理代码

                try(
                        FileInputStream fis = new FileInputStream("aaa.txt");
                        FileOutputStream fos = new FileOutputStream("bbb.txt");
                        MyClose mc = new MyClose();
                ){
                        int b;
                        while((b = fis.read()) != -1) {
                                fos.write(b);
                        }
                }
三.重点
* 1.拷贝文件
        * a.使用FileInputStream和FileOutputStream, 逐个字节拷贝,效率太低了
        * b.使用FileInputStream和FileOutputStream, 定义一个大数组(length等于文件大小), 一次性拷贝,有可能会内存溢出
        * c.使用FileInputStream和FileOutputStream, 定义一个小数组(例如1024), 多次拷贝
        * d.使用BufferedInputStream和BufferedOutputStream内置的缓冲区, 逐个字节拷贝
* 2.标准化IO流操作的代码
        * a.finally嵌套
        * b.try close
               

作者: め白衬衫    时间: 2014-10-16 11:34
这个头像好眼熟,好像我也有,哈哈。赞一个




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2