IO流

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Java_Road_Far/article/details/80322807

脑图:
这里写图片描述
1. 什么是IO流?
输入Input:读取外部数据到程序中;
输出output:将程序数据输出到存储设备中.
这里写图片描述
这里写图片描述


2.IO流体系:
这里写图片描述


3.流的分类:
1. 按照数据流向的不同:输入流(写) 输出流(读)
2. 按照处理数据的单位的不同:字节流 字符流(处理的文本文件)
3. 按照角色的不同:节点流(直接作用于文件的) 处理流(构造函数为流)
这里写图片描述
这里写图片描述


4.用字节输入流读文件 - FileInputStream

    /**
     * 输入
     */
    @Test
    public void testFileInputStream1(){
        FileInputStream fis = null;
        try {
            File file = new File("D:/IO/helloworld_IO.txt");
            if(!file.exists()){
                throw new RuntimeException("要读取的文件不存在");  
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[120];
            int len = 0;
            while((len = fis.read(b)) != -1){
                String string = new String(b, 0, len);
                System.out.println(string);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

5.用字节输入输出流复制文件 - FileInputStream & FileOutPutStream

    @Test
    public void testCopyFile(){
        System.out.println("start Copy.....");
        Long startTime = System.currentTimeMillis();
        copyFile(new File("D:/IO/helloworld_IO.txt"), new File("D:/IO/copy_helloworld_IO.txt"));
        Long endTime = System.currentTimeMillis();
        System.out.println("end Copy.....");
        System.out.println("总用时: " + (endTime - startTime) + "mm");
    }

    /**
     * 文件copy
     * FileInputStream
     * FileoutputStream: 写出的文件不存在时,创建文件并写入内容; 文件存在时,覆盖文件中的内容.
     */
    public void copyFile(File f1, File f2){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            if(!f1.exists()){
                throw new RuntimeException("要读取的文件不存在");  
            }
            fis = new FileInputStream(f1);
            fos = new FileOutputStream(f2);
            byte[] b = new byte[20];
            int len;
            while((len = fis.read(b)) != -1){
                fos.write(b, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

6.用字符输入输出流复制文件 FileReader & FileWriter

    @Test
    public void testFileReaderAndFileWriter(){
        FileReader fr = null;
        FileWriter fw = null;

        try {
            File reder = new File("D:/IO/helloworld_IO.txt");
            File writer = new File("D:/IO/helloworld_IO_Writer.txt");
            if(!reder.exists()){
                throw new RuntimeException("要读取的文件不存在");  
            }
            fr = new FileReader(reder);
            fw = new FileWriter(writer);
            char[] c = new char[200];
            int len;
            while((len = fr.read(c)) != -1){
                System.out.println(new String(c, 0, len));
                fw.write(c, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fw != null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if(fr != null){
                        try {
                            fr.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

7.用缓冲流复制文件 BufferedInputStream & BufferedOutputStream
处理流的一种,可以提升文件操作的效率。
这里写图片描述

    //BufferedOutputStream: 注意要 bufferedOutputStream.flush();
    @Test
    public void copyFile(){
        System.out.println("TestBufferedReaderAndBuferedWriter.copyFile()");
        long start = System.currentTimeMillis();
        testBufferedReaderWriter("D:/IO/helloworld_IO.txt", "D:/IO/helloworld_IO_bufferIOStream.txt");
        long end = System.currentTimeMillis();
        System.out.println("共用时: " + (end - start));
    }

    /**
     * 字节流复制文件
     * @param url
     * @param dest
     */
    public void testBufferedReaderWriter(String url, String dest){
        File f1 = new File(url);
        File f2 = new File(dest);
        if(!f1.exists()){
            throw new RuntimeException("要读取的文件不存在");
        }
        BufferedInputStream bis = null;
        BufferedOutputStream bos  = null;
        try {
            FileInputStream fis = new FileInputStream(f1);
            FileOutputStream fos = new FileOutputStream(f2);

            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            byte[] b = new byte[1024];
            int len;
            while((len = bis.read(b)) != -1){
                bos.write(b, 0, len);
                bos.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if(bis != null){
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

BufferedOutputStream类将写入的数据存储在缓冲区(一个名为buf的保护字节数组字段),直到缓冲区满或刷新缓冲区,然后它将数据一次写入底层输出流。

BufferedInputStream类也有一个作为缓冲区的保护字节数组,名为buf。当调用某个流的read方法时,它首先尝试从缓冲区读取数据。只有当缓冲区没有数据时,流才从底层的源中读取数据。这时它会从底层的源中读取尽可能多的数据进入缓冲区,而不管它是否马上需要这些数据。

默认情况下,输入流的缓冲区大小为2048字节,输出流的缓冲区大小为512字节。


8.用缓冲流复制文件 BufferReader & BufferedWriter

    //BufferedWriter: 注意 bufferedWriter.flush();
    @Test
    public void copyFile1(){
        System.out.println("TestBufferedReaderAndBuferedWriter.copyFile1()");
        long start = System.currentTimeMillis();
        testBufferedReaderAndWriter("D:/IO/helloworld_IO.txt", "D:/IO/helloworld_IO_bufferReader.txt");
        long end = System.currentTimeMillis();
        System.out.println("共用时: " + (end - start));
    }

    /**
     * 字符流复制文件
     */
    public void testBufferedReaderAndWriter(String url, String dest){
        File f1 = new File(url);
        File f2 = new File(dest);
        if(!f1.exists()){
            throw new RuntimeException("要读取的文件不存在");
        }
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            FileReader fr = new FileReader(f1);
            FileWriter fw = new FileWriter(f2);
            br = new BufferedReader(fr);
            bw = new BufferedWriter(fw);
            String str = null;
            while((str = br.readLine()) != null){
                bw.write(str);
                bw.newLine();
                bw.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bw != null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if(br != null){
                        try {
                            br.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

BufferedReader和BufferedWriter类是基于字符的,对应于上述的字节缓冲流。字节缓冲流使用一个内部字节数组作为缓冲区,字符缓冲流使用一个内部字符数组作为缓冲区。

默认情况下,字符缓冲流的缓冲区大小为8192字符


9.转换流 InputStreamReader & OutputStreamWriter
这里写图片描述
转换流提供在字节流和字符流之间的转换.

    什么时候需要用转换流:

    1、当需要指定编码方式的时候,那么就需要此转换流OutputStreamWriter。

    2、当需要指定编码方式的时候那么就需要转换流来操作。

    3、当需要读取别的编码方式的文件的时候,也得需要使用转换流

    4、字节流不用刷新缓冲区,字符流要刷新缓冲区
    /**
     * 字节转换为字符进而输出.
     */
    @Test
    public void test1() {
        FileInputStream fis = null;
        InputStreamReader isr = null;
        try {
            File file = new File("D:/IO/helloworld_IO.txt");
            if (!file.exists()) {
                throw new RuntimeException("指定文件不存在!");
            }
            fis = new FileInputStream(file);
            isr = new InputStreamReader(fis, "GBK");
            char[] c = new char[1024];
            int len;
            while ((len = isr.read(c)) != 0) {
                System.out.println(new String(c, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

InputStreamReader类包含一个底层输入流,可以从中读取原始字节。它根据指定的编码方式,将这些字节转换为Unicode字符。

OutputStreamWriter从运行的程序中接受Unicode字符,并使用指定的编码方式讲这些字符转换为字节,然后发送到底层输出流。

如果OutputStreamWriter(InputStreamReader)没有指定编码方式,就使用平台默认的编码方式。这是很糟糕的,所以尽可能地指定编码方式(UTF-8)。


10.标准的输入输出流
这里写图片描述

标准的输入流: System.in
标准的输出流: System.out

    @Test
    public void test1() {
        BufferedReader bis = null;
        try {
            InputStream in = System.in;
            InputStreamReader isr = new InputStreamReader(in);
            bis = new BufferedReader(isr);
            String str;
            while(true){
                System.out.println("输入字符串: ");
                str = bis.readLine();
                if(str.equalsIgnoreCase("e") || str.equalsIgnoreCase("exit")){
                    break;
                }
                String upperCase = str.toUpperCase();
                System.out.println(upperCase);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

11.打印流
这里写图片描述

    //打印到指定位置
    /**
     * 打印流: 字节流: PrintStream  字符流: PrintWriter
     */
    @Test
    public void printStreamWriter(){
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(new File("test.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        PrintStream ps = new PrintStream(fos, true);
        if(ps != null){
            System.setOut(ps);
        }
        for(int i = 0; i <= 255; i++){
            System.out.print((char)i);
            if(i % 50 == 0){
                System.err.println();
            }
        }
        ps.close();
    }

PrintStream的每个print()方法都将参数以可预见的方式转换为一个字符串,再用默认的编码方式写入底层的输出流。

println()方法也能完成相同的操作,但会在所写的行末尾追加一个与平台有关的行分隔符。在unix下是换行符\n,在Mac OS 9下是回车符\r,在windows下是回车/换行对(\r\n)。

另外PrintStream吞掉了所有的异常。

综上,除了调试查看信息打印到控制台外,谨慎使用打印流。


12.数据流

    /**
     * DataInputStream、DataOutputStream
     * 数据流: 用来处理基本数据类型、String、字节数组的数据
     */
    @Test
    public void testDataIOStream(){
        DataOutputStream dos = null;
        DataInputStream dis = null;
        try {
            FileOutputStream fos = new FileOutputStream("data.txt");
            dos = new DataOutputStream(fos);
            dos.writeUTF("一箪食, 一瓢饮, 在陋室, 人不堪其忧, 回不改其乐.");
            dos.writeBoolean(true);
            dos.writeLong(416666666);

            FileInputStream fis = new FileInputStream("data.txt");
            dis = new DataInputStream(fis);
            System.out.println(dis.readUTF());
            System.out.println(dis.readBoolean());
            System.out.println(dis.readLong());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(dos != null){
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

13.对象流
这里写图片描述

对象的序列化: 把Java 对象转换成二进制流,从而允许把这种二进制流保存在磁盘中,或者通过网络将这中二进制流传输到另一个网络节点上. 当其他程序获取了这中二进制流,就可以恢复成原来的 Java 对象。

/**
     * 对象流
     */
    @Test
    public void testObjectOutputStream(){
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        try {
            FileOutputStream fos = new FileOutputStream("person.txt");
            oos = new ObjectOutputStream(fos);
            oos.writeObject(new Person("张三", 12));
            oos.flush();
            oos.writeObject(new Person("李四", 22));
            oos.flush();

            ois = new ObjectInputStream(new FileInputStream("person.txt"));
            while(true){  
                try{  
                    Person dbn = (Person) ois.readObject();  
                    System.out.println(dbn);  
                }catch(EOFException e){  
                    break;  
                }catch(NullPointerException ee){  
                    continue;  
                }  
            }  

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


//Java 对象需 实现 Serializable 接口
class Person implements Serializable{

    private static final long serialVersionUID = 1L;

    String name;
    Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public Person() {
        super();
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页