zoukankan      html  css  js  c++  java
  • 字节流

    首先要知道:这四个类是抽象类,是一切字符字节输入输出流的父类,因为是抽象类,所以要通过子类来实例化,不能直接实例化;

    public abstract class InputStream implements Closeable;
    public abstract class OutputStream implements Closeable, Flushable;
    public abstract class Reader implements Readable, Closeable;
    public abstract class Writer implements Appendable, Closeable, Flushable;

     1)FileInputStream:

        public static void demo1() throws FileNotFoundException, IOException {
            FileInputStream fis = new FileInputStream("xxx.txt");    //创建流对象,个人认为,相当于一根管道
            int x = fis.read();            //从硬盘上读取一个字节,硬盘上都是以二进制的形式存储
            System.out.println(x);
            int y = fis.read();
            System.out.println(y);
            int z = fis.read();
            System.out.println(z);
            int a = fis.read();
            System.out.println(a);//文件的结束标志:-1
            int b = fis.read();
            System.out.println(b);
            fis.close();                                            //关流释放资源
        }

    打印的结果为:97、98、99、-1、-1

        /**
         * Reads a byte of data from this input stream. This method blocks
         * if no input is yet available.
       * * *
    @return the next byte of data, or <code>-1</code> if the end of the file is reached. * 返回值为0到255的int类型的值,返回值为字符的ACSII值(如a就返回97,n就返回110). * @exception IOException if an I/O error occurs. */ public native int read() throws IOException; //空参构造,返回读到的内容(第五点阐述有参构造)

     从最基本的开始,假如说相关路径下有文件"xxx.txt",文件上面有abc三个字母,从上面源码可以看出,调用一次read()方法,就读一个字母,返回下一个。结束的时候,就返回-1。

    所以可以利用循环来判断:

        private static void demo2() throws FileNotFoundException, IOException {
            FileInputStream fis = new FileInputStream("xxx.txt");    //创建流对象
            int b;
            //文件的结束标志:-1,所以定义-1就结束了
            while((b = fis.read()) != -1) {
                System.out.println(b);
            }
            fis.close();
        }

    read()方法读取的是一个字节,为什么返回是int,而不是byte(复制的,其实我看不懂)

      因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111,

    那么这11111111byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上,

    240凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型。

    2)FileOutputStream:

        public static void demo1() throws FileNotFoundException, IOException {
            //创建字节输出流对象,如果没有就自动创建一个
            FileOutputStream fos = new FileOutputStream("yyy.txt");        
            fos.write(97);    //虽然写出的是一个int数,但是到文件上的是一个字节,会自动去除前三个8位
            fos.write(98);
            fos.write(99);
            fos.close();
        }

     相关路径的文件"yyy.txt"就在里面写出了一个abc内容。

    如果继续在上面写一个,如下:

        public static void demo1() throws FileNotFoundException, IOException {
            //创建字节输出流对象,如果没有就自动创建一个
            FileOutputStream fos = new FileOutputStream("yyy.txt");        
    //        fos.write(97);    //虽然写出的是一个int数,但是到文件上的是一个字节,会自动去除前三个8位
    //        fos.write(98);
    //        fos.write(99);
            fos.write(100);
            fos.close();
        }

     则文件"yyy.txt"上面只会显示d内容,因为其会在原来的文件上面进行清空,再重新写。

    ******在创建对象的时候是如果没有这个文件会帮我创建出来

    ******如果有这个文件就会先将文件清空,是将里面的内容清空,再写入

    *****如果不想文件清空,想续写,则在后面加一个布尔值就可以了。

        private static void demo2() throws FileNotFoundException, IOException {
            FileOutputStream fos = new FileOutputStream("yyy.txt",true);    //如果想续写就在第二个参数传true
            fos.write(97);
            fos.write(98);
            fos.close();
        }

     3)拷贝:核心代码就是下面几行

        /*
         * 复制文件,图片,读一次一个字节,写一次一个字节
         */
        public static void demo1() throws FileNotFoundException, IOException {
            FileInputStream fis = new FileInputStream("双元.jpg");        //创建输入流对象,关联双元.jpg
            FileOutputStream fos = new FileOutputStream("copy.jpg");    //创建输出流对象,关联copy.jpg
            int b;
            while((b = fis.read()) != -1) {                                //在不断的读取每一个字节
                fos.write(b);                                            //将每一个字节写出
            }
            fis.close();                                                //关流释放资源
            fos.close();
        }

     一个一个字节去读,去写(去拷贝),所以这种方法特别耗时。读一次写一次,一共要读写900多万次,所以特别耗时。

    4)fis.available()  得到输入流文件的全部字节数

       /*
         * 不推荐使用,因为有可能会导致内存溢出
         */
        public static void demo3() throws FileNotFoundException, IOException {
            
            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();
            fos.close();
            
        }

    5)

    private native int readBytes(byte b[], int off, int len) throws IOException;
    
    //这个方法使用一个byte的数组作为一个缓冲区,每次从数据源中读取和缓冲区大小(二进制位)相同的数据并将其存在缓冲区中。
    //定义的数组长度为10,每次写进去的也是10
    /*
     * 1.从读取流读取一定数量的字节,如果比如文件总共是102个字节
     * 2.我们定义的数组长度是10,那么默认前面10次都是读取10个长度
     * 3.最后一次不够十个,那么读取的是2个
     * 4.这十一次,每次都是放入10个长度的数组.
     */
    public int read(byte b[]) throws IOException {   
         return readBytes(b, 0, b.length);
    }
    
    /*
     * 1.从读取流读取一定数量的字节,如果比如文件总共是102个字节
     * 2.我们定义的数组长度是10,但是这里我们写read(bytes,0,9)那么每次往里面添加的(将只会是9个长度),就要读12次,最后一次放入3个.
     * 3.所以一般读取流都不用这个而是用上一个方法:read(byte[]);
     */
    public int read(byte b[], int off, int len) throws IOException {   
         return readBytes(b, off, len);
    }
    
    注意:空参构造和有参构造返回的值内容是不一样

     关于read(byte[] buffer,int off, int len):可以看出:参数buffer表示建了多大长度的缓冲区;off表示把东东往第几个缓冲区放,所以就一般为0,要知道,为什么不在第0个放,而要浪费第0个的位置呢;len就表示每次往缓冲区放多少个东东;

    public static void main(String[] args) throws Exception {         
        InputStream is = null;                                        
        byte[] buffer = new byte[5];                                  
        char c;                                                       
                                                                      
        try {                                                         
            is = new FileInputStream("test.txt");// 里面的内容为:ABCDEFGHI  
            is.read(buffer, 1, 2);                                    
            for (byte b : buffer) {                                   
                if (b == 0) {                                         
                    c = '-';                                          
                } else {                                              
                    c = (char) b;                                     
                }                                                     
                System.out.print(c);                                  
            }                                                         
            System.out.println();                                     
            is.read(buffer, 1, 3);                                    
            for (byte b : buffer) {                                   
                if (b == 0) {                                         
                    c = '-';                                          
                } else {                                              
                    c = (char) b;                                     
                }                                                     
                System.out.print(c);                                  
            }                                                         
        } catch (Exception e) {                                       
            e.printStackTrace();                                      
        } finally {                                                   
            if (is != null)                                           
                is.close();                                           
        }                                                             
    }                                                                 

    输出:

    -AB--
    -CDE-

        public static void demo1() throws FileNotFoundException, IOException {
            //xxx.txt   文件内容上面为  97,98,99
            FileInputStream fis = new FileInputStream("xxx.txt");
            byte[] arr = new byte[2];
            int a = fis.read(arr);    //将文件上的字节读取到字节数组中,
                                    //返回的是读到的数组的长度,也就是读到的字节的个数
            System.out.println("a:"+a);                        //读到的有效字节个数
            for (byte b : arr) {                        //第一次获取到文件上的a和b
                System.out.println(b);
            }
            
            int c = fis.read(arr);
            System.out.println(c);
            for (byte b : arr) {
                System.out.println(b);
            }
            fis.close();
        }

     打印出:

    2、97、98
    1、99、98

    标准代码:

        public static void demo2() throws FileNotFoundException, IOException {
            FileInputStream fis = new FileInputStream("xxx.txt");
            FileOutputStream fos = new FileOutputStream("yyy.txt");
            
            byte[] arr = new byte[2];
            int len;
            while((len = fis.read(arr)) != -1) {   //结合上面的,其实第二次返回的长度等于1了
                fos.write(arr,0,len);              //这次每两个字节两个字节地读,比一开始一个个字节读快多了
            }                                      //但是在实际中,字节数组长度设置得更大
            
            fis.close();
            fos.close();
        }

     我们设置数组长度,就等于我们自己拿着篮子去买菜了,但是实际上在java中,java已经帮我们备好篮子了

    private static int defaultBufferSize = 8192;   //每次读取8192个字节
    
    public BufferedInputStream(InputStream in) {  //包装,装饰者模式
        this(in, defaultBufferSize);            
    }                                           
    
    public BufferedInputStream(InputStream in, int size) {         
        super(in);                                                 
        if (size <= 0) {                                           
            throw new IllegalArgumentException("Buffer size <= 0");
        }                                                          
        buf = new byte[size];                                      
    }                                                              

    * E.小数组的读写和带Buffered的读取哪个更快?

    * 定义小数组如果是8192个字节大小和Buffered比较的话

    * 定义小数组会略胜一筹,因为读和写操作的是同一个数组

    * Buffered操作的是两个数组

         * close方法
         * 具备刷新的功能,在关闭流之前,就会先刷新一次缓冲区,将缓冲区的字节全都刷新到文件上,再关闭,
         * close方法刷完之后就能写了
         * 只有满了才刷新,有点不厚道
         *
         * flush方法?
         * 具备刷新的功能,刷完之后还可以继续写,自动刷新啊 。。用户体验

     字节数组处理中文:

    public static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("yyy.txt");             
        byte[] arr = new byte[4];                                         
        int len;                                                          
        while((len = fis.read(arr)) != -1) {    //写中文随时出现乱码                             
            System.out.println(new String(arr,0,len));//码表转中文,string的构造方法                   
        }                                                                                                                                       
        fis.close();                                                      
    }                                                                     
    public static void main(String[] args) throws IOException {
        //demo1();                                             
        FileOutputStream fos = new FileOutputStream("zzz.txt");
        fos.write("我读书少,你不要骗我".getBytes()); //字节流写出中文,要转换                   
        fos.write("
    ".getBytes());  //换行                        
        fos.close();                                           
    }                                                          

     标准代码:但是实际上一般都不会写得那么麻烦(1.6版本)

    public static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = null;  //作用域问题,所以要放在外面                      
        FileOutputStream fos = null;  //如果下面两两端代码初始化失败                    
        try {                                                             
            fis = new FileInputStream("xxx.txt");                         
            fos = new FileOutputStream("yyy.txt");                        
                                                                          
            int b;                                                        
            while((b = fis.read()) != -1) {                               
                fos.write(b);                                             
            }                                                             
        }finally {   //一定要关流,所以finally                                    
            try{    //如果初始化失败,没有开启,则不用关闭                                  
                if(fis != null)                                           
                    fis.close();                                          
            }finally {            //try fianlly的嵌套目的是能关一个尽量关一个              
                if(fos != null)                                           
                    fos.close();                                          
            }                                                             
        }                                                                 
    }                                                                     

    1.7 版本之后流自动关闭,全实现了AutoCloseable接口,自动调用里面的close方法(这种方式开发中用得比较少)

    //当把流写在小括号里面,流就会自动关闭,为什么请见下面
    public
    static void main(String[] args) throws IOException { try( FileInputStream fis = new FileInputStream("xxx.txt"); FileOutputStream fos = new FileOutputStream("yyy.txt"); ){ int b; while((b = fis.read()) != -1) { fos.write(b); } } }
    public class FileInputStream extends InputStream;
    
    public abstract class InputStream implements Closeable;
    
    public interface Closeable extends AutoCloseable;
    
    /**
     * A resource that must be closed when it is no longer needed.
     *
     * @author Josh Bloch
     * @since 1.7
     */
    public interface AutoCloseable;

    END!

    END!

  • 相关阅读:
    angular手势事件之on-Hold
    angular 控制器的使用两种模式
    关于IONIC 报错 XX is not a function
    ionic 中$ionicView.beforeEnter 事件的一个bug
    开发一个IONIC应用的首要操作(宏观)
    在线常用库 + API手册
    关于日历实现代码里lunarInfo(农历)数组
    YSlow
    GET and POST
    Yahoo34条军规——雅虎WEB前端网站优化
  • 原文地址:https://www.cnblogs.com/ericguoxiaofeng/p/7913046.html
Copyright © 2011-2022 走看看