美文网首页
Java I/O流

Java I/O流

作者: 海人为记 | 来源:发表于2018-07-20 09:20 被阅读3次

    概念和作用

    流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象
    流的本质:数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行操作。
    流的作用:为数据源和目的地建立一个输送通道。
    Java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流。

    Java IO所采用的模型

    Java的IO模型设计非常优秀,它使用Decorator(装饰者)模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。
    例如:您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。

    Java IO流体系.jpg

    IO流的分类

    • 根据处理数据类型的不同分为:字节流(字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的)和字符流(字符流只能操作纯字符数据,比较方便)
    • 根据数据流向不同分为:输入流和输出流
    • 按数据来源分类:
      ①File(文件):FileInputStream, FileOutputStream, FileReader, FileWriter
      ②byte[]: ByteArrayInputStream, ByteArrayOutputStream
      ③Char[]: CharArrayReader, CharArrayWriter
      ④String: StringBufferInputStream, StringReader, StringWriter
      ⑤网络数据流: InputStream, OutputStream, Reader, Writer.
    Java IO流体系结构.png

    字节流 FileInputStream与FileOutputStream

    FileInputStream是InputStream抽象类的子类,以字节的形式来读取文件内容,它已经重写了read()方法。
    构造方法

    构造方法 描述
    public FileInputStream(String name) throws FileNotFoundException 根据字符串地址来连接到一个本地文件
    public FileInputStream(File file) throws FileNotFoundException 根据一个File类对象连接到一个本地文件

    常用方法

    方法 描述
    public int read() throws IOException 从此输入流中读取一个数据字节
    public int read(byte b[]) throws IOException 从此输入流中将最多b.length个字节的数据读入一个byte数组中
    public int read(byte b[], int off, int len) throws IOException 从此输入流中读取最多len个字节的数据读入到一个byte[]数组中
    public void close() throws IOException 关闭此输入流并释放与此流有关的所有系统资源
    public int available() throws IOException 获取资源中剩余的长度

    实例

    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class FileStream {
    
        public static void main(String[] args) throws IOException {
            //创建输入流连接
            FileInputStream inputStream = new FileInputStream("C:\\Users\\xxx\\Pictures\\IMG_2179.JPG");
            //定义接收数据的变量
            int i = 0;
            // 从输入流中读取一个数据字节(如果返回-1,说明已经到了文件的末尾
            while((i=inputStream.read()) != -1) {
                System.out.println(i);
            }
            //关闭流
            inputStream.close();
        }
    }
    

    FileOutputStream是OutputStream抽象类的子类,以字节的形式将数据写入到文件中,已经重写了write()方法
    构造方法

    方法 描述
    public FileOutputStream(String name) throws FileNotFoundException 根据字符串地址来连接到一个本地文件
    public FileOutputStream(String name, boolean append) throws FileNotFoundException 在文件末尾继续写入
    public FileOutputStream(File file) throws FileNotFoundException 根据一个File类对象连接到一个本地文件
    public FileOutputStream(File file, boolean append) throws FileNotFoundException 在文件末尾继续写入

    常用方法

    方法 描述
    public void write(int b) throws IOException 将指定字节写入此文件输出流
    public void write(byte b[]) throws IOException 将b.length个字节从指定byte数组写入此文件输出流中
    public void write(byte b[], int off, int len) throws IOException 将指定byte数组中从偏移量off开始的len个字节写入此文件输出量
    public void close() throws IOException 关闭输出流并是方法与此流有关的所有系统资源

    实例

    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class FileStream {
    
        public static void main(String[] args) throws IOException {
            //创建输出流连接
            FileOutputStream outputStream = new FileOutputStream("C:\\Users\\hireny\\Desktop\\learning\\exercise\\day017\\test.txt");
            //写入一个数据字节
            outputStream.write(97);
            //关闭流
            outputStream.close();
        }
    }
    

    上述的方法在你写入的时候,它会将你文件中的内容进行清空在开始写入,而FileOutputStream(String name, boolean append)或者FileOutputStream(File file, boolean append)这两个构造方法的第二个参数设置成true,它会将字节写入文件末尾处,不会从新开始写入。

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class FileStream {
    
        public static void main(String[] args) throws IOException {
            FileOutputStream outputStream = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\test.txt", true);
            FileInputStream inputStream1 = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\test1.txt");
            FileInputStream inputStream2 = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\test2.txt");
            FileInputStream inputStream3 = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\test3.txt");
            
            int i;
            while((i=inputStream1.read()) != -1)
                outputStream.write(i);
            while((i=inputStream2.read()) != -1)
                outputStream.write(i);
            while((i=inputStream3.read()) != -1)
                outputStream.write(i);
            
            inputStream1.close();
            inputStream2.close();
            inputStream3.close();
            outputStream.close();
        }
    }
    

    下面是两个小例子
    复制图片

    public static void copyPictures() throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\IMG_3502.JPG");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\IMG_3501.JPG"); 
        int i;
        while((i=fis.read()) != -1) {
            fos.write(i);
        }
        fis.close();
        fos.close();
    }
    

    复制歌曲

    public static void copyMusic() throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible(1).mp3");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible.mp3");  
        int i;
        while((i=fis.read()) != -1) {
            fos.write(i);
        }   
        fis.close();
        fos.close();
    }
    

    复制图片还可以,但是当我们复制歌曲的时候,执行的时间有点长,这是因为每次读取一个字节的速度太慢,实际开发中根本无法使用,因此,Java提供了获取多个字节的方法read(byte[] b),允许一次获取一个数组长度的字节

    public static void copyMusic() throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible(1).mp3");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible.mp3");  
        byte[] b = new byte[1024];
        while((fis.read(b)) != -1) {
            fos.write(b);
        }
        fis.close();
        fos.close();
    }
    

    这样的话,我们的写入的速度会非常快了,但是,如果最后一次获取的数组长度不到1024,还是会有稍微的浪费,因此,要使用下面的写法

    public static void copyMusic() throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible(1).mp3");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible.mp3");  
        byte[] b = new byte[1024*8];
        int len;
        while((len=fis.read(b)) != -1) {
            fos.write(b, 0, len);
        }
        fis.close();
        fos.close();
    }
    

    available()方法
    我们也可以使用available方法来帮我们获取资源中剩余的长度

    public static void copyMusic() throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible(1).mp3");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible.mp3");  
    
        //创建一个和资源文件大小相同的字节数组
        byte[] b = new byte[fis.available()];
        fis.read(b);
        fos.write(b);
        fis.close();
        fos.close();
    }
    

    如果资源文件过大,很容易造成内存溢出,获取长度的素的极慢,不可取。

    字节缓冲流 BufferedInputStream与BufferedOutputStream

    缓冲输入流BufferedInputStream
    BufferedInputStream继承于FileInputStream,它的作用是为另一个输入流添加一些功能,本质上是通过一个内部缓冲数组实现的。例如,在新建某输入流对应的BufferedInputStream后,当通过read()读取数据时,BufferedInputStream会将输入流的数据分批的填入到缓冲区中,每当缓冲区的数据读完之后,输入流会再次填充数据缓冲区,直到读完数据。
    构造方法

    方法 描述
    public BufferedInputStream(InputStream in) 创建一个BufferedInputStream并保存其参数,即输入in,以便将来使用
    public BufferedInputStream(InputStream in, int size) 创建一个具有缓冲区大小的BufferedInputStream并保存其参数,即输入流in,以便将来使用

    常用方法

    方法 描述
    public synchronized int read() throws IOException 一次读取一个字节
    public synchronized int read(byte[] b, int off, int len) throws IOException 从此字节输入流中给定偏移量处开始各字节读取到指定的byte数组中
    public void close() throws IOException 关闭并释放资源,实际关闭的是内部真正工作的字节流

    实例

    //字节缓冲输入流的使用 BufferedInputStream
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\hireny\\Desktop\\exercise\\IMG_3503.JPG");
        BufferedInputStream bis = new BufferedInputStream(fis);
        int i;
        while((i=bis.read()) != -1) {
            System.out.println(i);
        }
        //关闭缓冲流就会关闭字节流
        bis.close();
    }
    

    注意事项:BufferedInputStream内部建立一个缓冲区域,在读取文件的时候,一次性读取大量的字节,缓冲到缓冲区当中,然后再返给我们,看着没有变化,区别在于一个直接操作硬盘,一个是操作内存,效率不可相提并论
    缓冲输出流BufferedOutputStream
    BufferedOutputStream继承于FileOutputStream,它的作用是实现缓冲的输出流,通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
    构造方法

    方法 描述
    BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层的输出流
    BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流

    常用方法

    方法 描述
    void write(int b) 将指定的字节写入此缓冲流的输出流
    void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流
    void flush() 刷新此缓冲的输出流
    void close() 关闭流,并释放资源

    实例

        //字节缓冲输出流的使用 BufferedOutputStream
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\text.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        for(int i = 0; i < 100000; i++) {
            bos.write(i);
        }
        bos.close();
    }
    

    注意事项:缓冲流就是一个壳子,它不能实际和本地文件建立连接,本质上还是通过InputStream和OutputStream来工作

    使用字节缓冲流来实现文件的复制

        //使用字节缓冲流来实现文件的复制
        public static void useBufferedInputOutputStream() throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible.mp3");
        BufferedInputStream bis = new BufferedInputStream(fis);
        FileOutputStream fos = new FileOutputStream("C:\\Users\\xxx\\Desktop\\exercise\\Delacey - Dream It Possible(2).mp3");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int s;
        while((s=bis.read()) != -1) {
            bos.write(s);
        }
        bos.flush(); // 如果你不关闭 bos.close()缓冲流,那你就要手动进行刷新,否则会丢失一些字节流
        bis.close();
        bos.close();
    }
    

    小数组和缓冲流的效率问题:定义小数组如果是8192个字节大小和Buffered比较的话(小数组和Bufered大小相差不打的情况下),小数组快;定义小数组会略胜一筹,因为读和写操作的是同一个数组;而Buffered操作的是两个数组

    流的异常处理问题

    jdk1.6及以前的版本处理方式

    public static void main(String[] args)  {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("d:\\骑在银龙的背上.mp3");
            fos = new FileOutputStream("d:\\音乐副本.mp3");
            int i ;
            while((i=fis.read())!= -1){
                fos.write(i);
            }
        } catch (Exception e) {
            
        }finally {
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
                
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    JDK1.7的处理方式
    在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}(读写代码)执行后就会自动调用,流对象的close方法将流关掉

    public static void main(String[] args)  {
        try(
            FileInputStream fis = new FileInputStream("d:\\骑在银龙的背上.mp3");
            FileOutputStream fos = new FileOutputStream("d:\\音乐副本.mp3");
        ){
            int i ;
            while((i=fis.read())!= -1){
                fos.write(i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    字符流

    • 字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码
    • 字符流只用来处理文本数据,字节流用来处理媒体数据
    • 数据最常见的表现方式是文件,字符流用于操作文件的子类一般是FileReader和FileWriter

    字符流读写
    注意事项:

    • 写入文件后必须要用flush()刷新
    • 用完流后记得要关闭流
    • 使用流对象要抛出IO异常
    • 定义文件路径时,可以用"/"或者"\"
    • 在创建一个文件时,如果目录下有同名文件将被覆盖
    • 在读取文件时,必须保证该文件已存在,否则出异常

    字符流FileReader与FileWriter

    FileReader

    字符输入流,底层使用的还是字节流
    构造方法

    方法 描述
    public FileReader(String fileName) throws FileNotFoundException 根据字符串路径和文件获取连接
    public FileReader(File file) throws FileNotFoundException 根据File对象和文件获取连接

    常用方法

    方法 描述
    public int read() throws IOException 读取单个字符
    public int read(char cbuf[]) throws IOException 将字符读入数组
    public void close() throws IOException 关闭该流并释放资源

    实例

    import java.io.FileReader;
    import java.io.IOException;
    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\text.txt";
        FileReader fr = new FileReader(path);
        char[] chs = new char[1024];
        int len;
        while((len=fr.read(chs)) != -1) {
            System.out.println(new String(chs, 0, len));
        }
        fr.close();
    }
    // 读取的是你text.txt的文本信息。
    
    FileWriter

    字符输出流,将字符写入到文件中,可以直接写入字符串;字符输出流中是有缓冲区的。
    构造方法

    方法 描述
    public FileWriter(String fileName) throws FileNotFoundException 根据字符串路径和文件获取连接
    public FileWriter(File file) throws FileNotFoundException 根据File对象和文件获取连接
    public FileWriter(File file, boolean append) throws FIleNotFoundException 根据File对象和文件获取连接,让流可以从尾部写入

    常用方法

    方法 描述
    public Writer append(char c) throws IOException 将指定字符写入到此writer,功能等同于write()
    public void write(int c) throws IOException 写入单个字符
    public void write(char cbuf[]) throws IOException 将字符数组写入
    public void write(String str) throws IOException 将字符串写入
    public void write(String str, int off, int len) throws IOException 将字符串从0到len截取写入
    public void flush() throws IOException 手动刷新
    public void close() throws IOException 关闭该流并释放资源

    实例

    import java.io.FileWriter;
    import java.io.IOException;
    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\frequency.txt";
        FileWriter fr = new FileWriter(path);
        fr.append('天');
        fr.write('地');
        char[] c = {'a','b','c'};
        fr.write(c);
        fr.write("什么");
        fr.write("都是这些惹的祸", 0, 4);
        fr.flush();
        fr.close();
    }
    

    使用自定义数组进行存储,和字节流使用数组一样

    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\text.txt";
        String target = "C:\\Users\\xxx\\Desktop\\exercise\\frequency.txt";
        FileReader reader = new FileReader(path);
        FileWriter fr = new FileWriter(target); 
        char[] chs = new char[1024];
        int len;
        while((len=reader.read(chs)) != -1) 
            fr.write(chs, 0, len);
        reader.close();
        fr.close();
    }
    

    字符流的缓冲区

    字符流提供了带缓冲区的包装流,分别是BufferedReader和BufferedWriter,其中BufferedReader用于对字符输入流进行包装,BufferedWriter用于对字符输出流进行包装。
    缓冲区的出现提高了对数据的读写效率
    特点:缓冲区要结合刘彩盒使用,在创建缓冲区之前,必须要有流对象,在流的基础上对流的功能进行了增强。

    字符读取缓冲流 BufferedReader

    从字符输入流冲读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取

    方法 描述
    BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流
    BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流
    String readLine() 读取一个文本行
    字符写入缓冲流 BufferedWriter

    将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入

    方法 描述
    BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流
    BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流
    void newLine() 写入一个行分隔符

    实例

    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\text.txt";
        String target = "C:\\Users\\xxx\\Desktop\\exercise\\frequency.txt";
        BufferedReader br = new BufferedReader( new FileReader(path));
        BufferedWriter bw = new BufferedWriter( new FileWriter(target));        
        String str;
        while((str=br.readLine()) != null) {
            bw.write(str);
            bw.newLine();
        }
        br.close();
        bw.close();
    }
    
    LineNumberReader

    是BufferedReader的子类,具有相同的功能,并且可以统计行号,默认是从0开始的

    方法 描述
    getLineNumber() 方法可以获取当前行号
    setLineNumber() 方法可以设置当前行号

    实例

    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\text.txt";
        LineNumberReader lnr = new LineNumberReader(
                new FileReader(path));
        String str;
        System.out.println(lnr.getLineNumber());
        lnr.setLineNumber(2);
        while((str=lnr.readLine()) != null)
            System.out.println(str+":"+lnr.getLineNumber());
            
        lnr.close();
    }
    

    注意事项:行号默认从0开始;readLine方法每走一次,行号+1

    转换流

    转换流是Reader和Writer的子类,可以在字节流和字符流之间进行转换
    InputStreamReader是字节流通向字符流的桥梁,读取字节并将其解码为字符

    InputStreamReader构造方法

    方法 描述
    InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader
    InputStreamReader(InputStream in, Charset cs) 创建使用给定字符集的InputStreamReader
    InputStreamReader(InputStream in, String charsetName) 创建使用指定的字符集的InputStreamReader
    InputStreamReader(InputStream in, CharsetDecoder dec) 创建使用给定字符集解码器的 InputStreamReader

    InputStreamReader常用方法

    方法 描述
    void close() 关闭该流并释放与之关联的所有资源
    String getEncoding() 返回此流使用的字符编码的名称
    int read() 读取单个字符
    int read(char[] cbuf, int offset, int length) 将字符读入数组的某一部分
    boolean ready() 判断此流是否已经准备好用于读取

    OutputStreamWriter是字符流通向字节流的桥梁,将要写入流中的字符编码成字节
    OutputStreamWriter构造方法

    方法 描述
    OutputStreamWriter(OutputStream out) 创建使用默认字符编码的OutputStreamWriter
    OutputStreamWriter(OutputStream out, Charset cs) 创建使用给定字符集的OutputStreamWriter
    OutputStreamWriter(OutputStream out, CharsetEncoder enc) 创建使用给定字符集编码器的OutputStreamWriter
    OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的OutputStreamWriter

    OutputStreamWriter常用方法

    方法 描述
    void close() 关闭此流,但要先刷新它
    void flush() 刷新该流的缓冲
    String getEncoding() 返回此流使用的字节编码的名称
    void write(char[] cbuf, int off, int len) 写入字符数组的某一部分
    void write(int c) 写入单个字符
    void write(String str, int off, int len) 写入字符串的某一部分

    实例

    public static void conversionStream() {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\text.txt";
        String target = "C:\\Users\\xxx\\Desktop\\exercise\\text2.txt";
        try (
                BufferedReader br = new BufferedReader(
                            new InputStreamReader(
                                    new FileInputStream(path), "GBK"));
                BufferedWriter bw = new BufferedWriter(
                            new OutputStreamWriter(
                                    new FileOutputStream(target), "UTF-8"));
                ) {
            String str;
            while((str=br.readLine()) != null) {
                System.out.println(str);
                bw.write(str);
                bw.newLine(); // 换行符
            }
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
    

    序列流

    序列流可以把两个字节输入流整合成一个,从序列流中读取数据时,将从被整合的第一个流开始读,读完一个之后继续读第二个,以此类推
    实例

        // 序列流
        public static void sequenceStream() throws IOException {
        String path1 = "frequency.txt";
        String path2 = "text.txt";
        String path3 = "\times.txt";
        // 创建输入流对象,关联path1
        FileInputStream fis1 = new FileInputStream(path1);
        // 创建输入流对象,关联path2
        FileInputStream fis2 = new FileInputStream(path2);
        //将两个流整合成一个流
        SequenceInputStream sis = new SequenceInputStream(fis1,fis2);
        // 创建输出流对象,关联path3
        FileOutputStream fos = new FileOutputStream(path3);
            
        int b;
        // 用整合后的读
        while((b=sis.read()) !=-1) {
            //写到指定的文件上
            fos.write(b);
        }
        sis.close();
        fos.close();
    }
    

    内存流

    该输出流可以向内存中写数据,把内存当作一个缓冲区,写出之后可以一次性获取出所有数据;不和本地文件进行交互;不需要关闭,关闭了还能使用
    分类:
    ByteArrayOutputStream 内存储存流(内存输出流,从程序到内存)
    ByteArrayInputStream 内存读取流(内存输入流,从内存到程序)
    实例

    // 内存流
    public static void main(String[] args)  throws IOException {
        String path = "C:\\frequency.txt";
        FileInputStream fis = new FileInputStream(path1);
            
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int i;
        while((i=fis.read()) != -1) {
            baos.write(i);
        }
            
        // 将内存缓冲区中所有的字节存储在newArr中
        byte[] newArr = baos.toByteArray();
        System.out.println(new String(newArr));
        System.out.println(baos);
            
        ByteArrayInputStream bais = new ByteArrayInputStream(newArr);
            
        while((i=bais.read()) != -1) 
            System.out.println(i);
            
        fis.close();
    }
    

    对象操作流(序列化流)

    该流可以将一个对象写出,或者读取一个对象到程序中,也就是执行了序列化和反序列化的操作;可以将集合中的对象一次性写入本地;写入本地的对象必须实现Serializable接口

    分类
    ObjectOutputStream 将对象写入到本地
    ObjectInputStream 从本地读取文件生成对象
    实例

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student p1 = new Student("小明",20);
        Student p2 = new Student("小清",21);
            
        //无论是字节输出流,还是字符输出流都不能直接写出对象
        //将对象写入到本地
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\student.txt";
        ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(path));
        oos.writeObject(p1);
        oos.writeObject(p2);
        oos.writeObject(null); // 读取的时候如果后面已经没有对象了,就会报错
        oos.close();
            
        ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(path));
        Object student;
        // 当读到文件尾部再次读取的会报错
        while((student=ois.readObject()) != null) 
            System.out.println(student);
            
        ois.close();
    }
    

    数据流

    按照基本数据类型的大小写入读取数据;例如按Long大小写出一个数字, 写出时该数据占8字节. 读取的时候也可以按照Long类型读取, 一次读取8个字节

    实例

        // 数据流
    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\text.txt";
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(path));
        dos.writeInt(997);
        dos.writeInt(998);
        dos.writeInt(999);
            
        dos.close();
            
        DataInputStream dis = new DataInputStream(new FileInputStream(path));
        int x = dis.readInt();
        int y = dis.readInt();
        int z = dis.readInt();
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);
        dis.close();
    }
    

    打印流

    该流可以很方便的将对象的toString()结果输出,并且可以自动加上换行,而且可以使用自动刷出的模式;具有方向性。
    分类
    PrintStream 数据的表现形式
    PrintWriter 数据的表现形式(不包含输出字节)
    实例

    // 打印流
    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\xxx\\Desktop\\exercise\\test.txt";
        //自动刷新的模式
        PrintWriter pw = new PrintWriter(new FileOutputStream(path));
        pw.write(97);
        pw.print("大家好");
        pw.println("你好");  // 自动刷出,只针对的是println方法
        pw.print("就是");
        pw.close();
    }
    

    相关文章

      网友评论

          本文标题:Java I/O流

          本文链接:https://www.haomeiwen.com/subject/jyanpftx.html