IO流

脑图:
这里写图片描述
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 + "]";
    }

}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Java_Road_Far/article/details/80322807
文章标签: Java IO
个人分类: java
想对作者说点什么? 我来说一句

Javaio流思维导图

2018年02月21日 356KB 下载

文件流总结

2018年03月31日 29KB 下载

IO流读取和创建文件

2011年06月17日 5.19MB 下载

Java的例外处理和IO

2009年04月25日 106KB 下载

JAVA IO流小结

2011年08月29日 27KB 下载

IO流和异常处理

2017年12月27日 40KB 下载

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

不良信息举报

IO流

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭