Bootstrap

IO流详解.

目录: 

一、IO流概述
二、FileInputStream初步
三、FileOutStream的使用
四、文件复制
五、FileReader的使用 
六、FileWriter的使用
七、复制普通文本文件
八、带有缓冲区的字符流
九、标准输出流(掌握)    / 写日志
十、File类

一、IO流概述

IO流: 什么是IO?
I:Input
O:Output        
(断电内存数据消失)

 1.1、IO流的分类

Io流的分类?
有多种分类方式:
    一种方式是按照流的方向进行分类:
    以内存作为参照物,往内存中去,叫做输入(Input)。或者叫做读(Read)。从内存中出来,叫做输出(Output)。或者叫做写(Write)

    另一种方式是按照读取数据方式不同进行分类:
    有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制
    这种流是万能的,什么类型的文件都可以读取包括:文本文件,图片,声音文件,
        假设文件file.txt,采用字节流的话是这样读的:
            a中国bc张三fe
            第一次读: 一个字节,正好读到'a'
            第二次读:一个字节,正好读到'中'字符的一半。
            第三次读: 一个字节,正好读到'中'字符的另外一半。


    有的流是按照字符的方式读取数据的,一次读取一一个字符,这种流是为了方便读取
    普通文本(.txt)文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯
    文本文件,连word文件都无法读取。
        假设文件file1. txt,采用字符流的话是这样读的:
            a中国bc第一fe
            第一次读: 'a'字符 ('a'字符在windows系统中占用1个字节。)
            第二次读: '中'中字符('中'字符在windows系统中占用2个字节。)

综上所述:流的分类
    输入流、输出流
    字节流、字符流

1.2、java Io流这块有四大家族

四大家族的首领: 
    java.io.Inputstream    字节输入流
    java.io.Outputstream    字节输出流
    java.io.Reader    字符输入流
    java.io.Writer    字符输出流
    
    四大家族的首领都是抽象类。(abstract class)
    注意:在java中只要"类名"以stream结尾的都是字节流。以"Reader/Writer"结尾的都是字符流
    
    所有的流都实现了:
        java.io.closeable接口,都是可关闭的,都有close()方法。
        流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,
        不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。
    
    所有的输出流都实现了:
        java.io.Flushable接口,都是可刷新的,都有flush()方法。
        养成一个好习惯,输出流在最终输出之后,一定要记得flush()
        刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据
        强行输出完(清空管道!)刷新的作用就是清空管道。
        注意:如果没有flush()可能会导致丢失数据。

 1.3、需要掌握哪些流(16个)

文件专属:(重点)
    java.io.FileInputstream(掌握)
    java.io.FileOutputstream(掌握)
    java.io.FileReader
    java.io.FileWri ter
转换流:(将字节流转换成字符流)
    java.io.InputstreamReader
    java.io .OutputstreamWri ter
缓冲流专属:
    java.io.BufferedReader
    java.io.BufferedWriter
    java.io.BufferedInputstream
    java.io.BufferedOutputstream
数据流专属:(了解)
    java.io.DataInputStream
    java.io.DataOutputstream
标准输出流:
    java.io.PrintWriter
    java.io.Printstream(掌握)
对象专属流:
    java.io.ObjectInputStream(掌握)
    java.io.Objectoutputstream(掌握)

二、FileInputStream初步

这个文件字节输入流直接看后面的结论代码即可,前面写的有点杂乱 大佬们多包涵~

代码演示如下:

这种一个一个读流的方式明显效率很低, 

package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
FileInputStream :
    1、文件字节输入流,万能的,任何类型的文件都可以采用这个流来读
    2、字节的方式,完成输入的操作,完成读的操作(硬盘----> 内存)

 */
public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileInputStream fis =null;
        // 创建一个FileInputStream对象
        try {
             fis =new FileInputStream("D:\\IdeaProjects\\hello\\hello.txt");
             // 读流
            try {
                int file1 =fis.read();
                System.out.println(file1);
                int file2 =fis.read();
                System.out.println(file2);
                int file3 =fis.read();
                System.out.println(file3);
                int file4 =fis.read();
                System.out.println(file4);
                int file5 =fis.read();
                System.out.println(file5);
                int file6 =fis.read();
                System.out.println(file6);

            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            // 在finally语句块当中确保流一定关闭
            // 关闭流的前提是:流不是空,流是null的时候没必要关闭
            if (fis!=null){ // 避免空指针异常
            try {
                fis.close();
                System.out.println("流关闭成功");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        }
    }
}

输出结果: 

read()读取流的方法执行原理图:

将以上代码改进为循环读流:

代码演示如下: 

package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

// 循环读流
public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileInputStream fis =null;
        // 创建一个FileInputStream对象
        try {
            fis =new FileInputStream("D:\\IdeaProjects\\hello\\hello.txt");
            // 读流
            try {
                /* 循环读流 第一种
               while (true){
                   int fisData =fis.read(); // 读流
                   if (fisData==-1){
                       break;
                   }
                   System.out.println(fisData);
               }*/

                // 第二种循环方式:
                int readData =0;
                while ((readData =fis.read())!=-1){ // 将读出来的字节赋给readData 然后依次和-1比较
                    System.out.println(readData);
                }

            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            // 在finally语句块当中确保流一定关闭
            // 关闭流的前提是:流不是空,流是null的时候没必要关闭
            if (fis!=null){ // 避免空指针异常
                try {
                    fis.close();
                    System.out.println("流关闭成功");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 输出结果:

 IDEA中的当前路径【重点】

 IDEA当前路径默认在工程Project的根

当寻找路径文件的时候会首先在工程根的目录下开始往下一步一步的寻找文件

 

这样写才是正确的 

七、

当返回的字节数量为0的时候(也就是文件里面没有元素的时候)返回-1 

 代码演示如下:

package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest03 {
    public static void main(String[] args) {

        // 创建一个FileInputStream对象    文件字节输入流(硬盘----->内存)
        try {
            FileInputStream fis =new FileInputStream("chapter15\\src\\com\\bjpowernode\\java\\io\\tempFile.txt");
            // 可以先读进数组里面
            // 开始读,采用byte数组,一次读取多个字节,最多读取”数组.length“个字节
            byte[] bytes =new byte[4];  // 准备一个4个长度的byte数组,一次最多读取4个字节
            try {
                int readCount =fis.read(bytes);   // 这个方法返回值是:读取到的字节数量(不是字节本身) 读到4个
                System.out.println(readCount);    // 4个字节
                System.out.println(new String(bytes,0,readCount));   // 将字节数组全部转换成字符串

                int fisCount1 =fis.read(bytes);  // 读取到的字节数量 读取2个
                System.out.println(fisCount1);   // 2个字节
                System.out.println(new String(bytes,0,fisCount1));  // 把数组中的字节转换成字符串    不用下标限制的话 会输出efcd(看图)

                int fisCount2 =fis.read(bytes); // 读取的字节数量  读到0个
                System.out.println(fisCount2);  // 当文件里面的元素读完之后 输出结果为-1


            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

 改进循环:【终极版 会这个就行】【记住这个】

代码演示如下:

package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest03 {
    public static void main(String[] args) {
        // 创建FileInputStream对象
        FileInputStream fis =null;
        try {
            fis =new FileInputStream("chapter15\\src\\com\\bjpowernode\\java\\io\\tempFile.txt");
            // 读流
            // 初始化一个数组
            byte[] bytes =new byte[4];
            while (true){
                try {
                    int fisCount =fis.read(bytes);  // 拿到的是字节数量
                    if (fisCount==-1){  // 字节数量为-1的时候说明文件里面没有元素了(读到了0个字节)
                        break;
                    }
                    // 能运行到这里说明文件还没有读取完
                    System.out.println(new String(bytes,0,fisCount));   // 把byte数组转换成字符串,读到多少个转换多少个

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            if (fis != null) {
                try {
                    fis.close();
                    System.out.println("流关闭成功");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

输出结果:

升级版:一定会这个

package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest03 {
    public static void main(String[] args) {
        FileInputStream fis =null;
        try {
            fis =new FileInputStream("chapter15\\src\\com\\bjpowernode\\java\\io\\tempFile.txt");
            // 初始化一个数组
            byte[] bytes =new byte[4];    
            // 读流
            /*while (true){
                int readCount =fis.read(bytes); // 往数组里面读 读取的是字节数量
                if (readCount==-1){
                    break;
                }
                System.out.println(new String(bytes,0,readCount));
            }*/
            
            // 升级版
            int readCount =0;
            while ((readCount =fis.read(bytes))!=-1){   // 把每次循环读的字节数量赋给readCount 然后与-1判断 等于-1的话该分支结束
                // 循环里面的fis.read(bytes))!=-1,只要不为-1,就一直在往bytes数组里面读取着数据呢,这时数组中已经一直有读取到的数据了。

                System.out.println(new String(bytes,0,readCount)); // 可以验证出确实bytes数组中确实读取到了数据
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {    // 在finally语句块当中确保流一定关闭(因为如果前面的代码出现异常了,但是finally块还是能执行了,所以在finally块中关闭流确保了流的关闭)
            // 关闭流的前提是:流不是空,流是null的时候没必要关闭

            if (fis != null) {    // 避免空指针异常
                try {
                    fis.close();
                    System.out.println("流关闭成功");
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

当文件内容不太大的时候,可以用下列方法一次读取完内容 【一定要会】

FileInputStream类的其他常用方法:
        int available()  : 返回流当中剩余的没有读到的字节数量
        long skip(long n) : 跳过几个字节不读 

代码演示如下: 

package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest04 {
    public static void main(String[] args) {
        // 创建FileInputStream对象
        FileInputStream fis =null;
        try {
            fis =new FileInputStream("chapter15/src/com/bjpowernode/java/io/UserFile");
            // 还没有读的时候文件中的总字节数量:
            // System.out.println("文件中的总字节数量:"+fis.available());   // 5
            // 读一个字节
            // int readData =fis.read();
            // 文件中还剩下可以读的字节数量是:     (文件中数据:abcde)
            // System.out.println("剩下多少字节没有读:"+fis.available());   // 4

            
            // int available() 这个方法可以怎么用呢?
            // : 当文件中的数据不太大的时候可以直接把总字节数量放入一个数组里面一次读取完(注意:当文件过大时不能直接放到数组当中:扩容问题影响效率)
            byte[] bytes =new byte[fis.available()];    // 直接把文件中的总字节数量放到数组里面
            // 不需要循环了
            // 直接一次读就行了
            int readData1 =fis.read(bytes);    // 读到数组里面 读到的是字节数量
            System.out.println(readData1);  // 5
            System.out.println(new String(bytes));  //abcde  直接把数组转换成字符串


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                // 关闭流
                try {
                    fis.close();
                    System.out.println("流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

三、FileOutStream的使用

文件字节输出流
从内存 ---->硬盘

代码演示如下: 

package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutStreamTest01 {
    public static void main(String[] args) {
        FileOutputStream fos =null;

        // 注意:这种方式谨慎使用,这种方式会先将原文件清空,然后重写写入
        
        try {
            fos =new FileOutputStream("OutputStreamFile");    // 新文件
            // 开始写
            byte[] bytes ={97,98,99,100,101};
            // 将byte数组全部写到硬盘
            fos.write(bytes);   // 将数组里面的内容写入到”OutputStreamFile”文件里面(当文件不存在的时候自动新建到项目根目录)
            // 将byte数组的一部分写到硬盘
            fos.write(bytes,0,2);   // 从0开始2个长度 ab
            
            // 写完之后一定要刷新
            fos.flush();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                    System.out.println("流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

输出结果:

注意:这里会先清空原文件当中的内容,然后把abcde和ab重写写入到该文件当中

 对以上缺点进行改进代码演示如下:

// 以追加的方式在文件末尾写入,不会清空原文件内容
package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

// 以追加的方式在文件末尾写入,不会清空原文件内容
public class FileOutStreamTest02 {
    public static void main(String[] args) {
        FileOutputStream fos =null;
        try {
            fos =new FileOutputStream("chapter15/src/com/bjpowernode/java/io/tempFile.txt",true);   // 追加的构造方法
            // 开始写
            byte[] bytes ={97,98,99,100,101};
            fos.write(bytes);

            // 也可以写字符串形式,然后把字符串转换成数组格式
            String s ="我是中国人,我爱中国,中国加油,中国之国~";
            byte[] bytes1 =s.getBytes();    // 将字符串转换成数组
            fos.write(bytes1);  // 把该数组当中的内容写入到文件当中

            // 刷新管道
            fos.flush();
            System.out.println("流刷新成功~");
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                    System.out.println("流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 输出结果:

 四、文件复制

使用FileInputStream + FileOutputStream完成文件的拷贝
拷贝的过程应该是一边读,一边写
使用以上的字节流拷贝文件的时候,文件类型随意,万能的,什么样的文件都能拷贝

思想如图所示: 

代码演示如下: 

注意:如果拒绝访问就以管理员的身份进入IDEA

package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyTest01 {
    public static void main(String[] args) {
        FileInputStream fis =null;
        FileOutputStream fos =null;
        try {
            // 把D盘中的文件复制到C盘

            // 创建一个输入流对象
            fis =new FileInputStream("D:\\画图总部\\面向对象思想图.png");
            // 创建一个输出流对象
            fos =new FileOutputStream("C:\\面向对象思想图.png");

            // 核心 : 一边读一边写
            byte[] bytes =new byte[1024 *1024]; // 以1MB拷贝
            int readCount =0;   // 数组的字节数量
            while ((readCount = fis.read(bytes))!=-1){   // 从文件中读进数组里面 只要不为-1就一直读,为-1说明读取完了
                // 写
                fos.write(bytes,0,readCount);   // 边读边写入
            }

            // 刷新,输出流最后要刷新
            fos.flush();
            System.out.println("输出流刷新成功~");
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 注意:分开try,不要一起try
            // 一起try的时候,其中一个出现异常,可能会影响到另外一个流的关闭
            if (fis != null) {
                try {
                    fis.close();
                    System.out.println("输入流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                    System.out.println("输出流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

五、FileReader的使用 

FileReader:
    文件字符输入流,只能读取普通文本
    读取文字内容时,比较方便,快捷

代码演示如下:(比葫芦画瓢~)

package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest01 {
    public static void main(String[] args) {
        // 创建一个FileReader对象
        FileReader fr =null;
        try {
            // 创建文件字符输入流
            fr =new FileReader("chapter15/src/com/bjpowernode/java/io/UserFile");
            // 开始读
            char[] chars =new char[4];
            int readCount =0;
            while ((readCount =fr.read(chars))!=-1){
                System.out.println(new String(chars,0,readCount));
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                    System.out.println("流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

输出结果:

六、FileWriter的使用

代码演示如下:(比葫芦画瓢)

package com.bjpowernode.java.io;
import java.io.FileWriter;
import java.io.IOException;

public class FileWriterTest01 {
    public static void main(String[] args) {
        FileWriter fw =null;
        try {
            fw =new FileWriter("chapter15/src/com/bjpowernode/java/io/UserFile");
            // 开始写
            char[] chars ={'我','是','中','国','人'};
            fw.write(chars);    // 全部写入
            fw.write(chars,2,3);    // 中国人 2是开始位置3是长度
            // 注意这里: 再一次运行该程序的时候 首先会把原文件中的内容清空 然后把我是中国人中国人写入该文件当中

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fw != null) {
                try {
                    fw.close();
                    System.out.println("流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 七、复制普通文本文件

使用FileReader、FileWriter进行拷贝演示,只能拷贝“普通文件”(能用记事本打开编写的都是普通文件)

代码演示如下:

package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTest02 {
    public static void main(String[] args) {
        FileReader fr =null;
        FileWriter fw =null;
        try {
            // 创建字符输入流对象
            fr =new FileReader("chapter15/src/com/bjpowernode/java/io/UserFile");
            // 创建字符输出流对象
            fw =new FileWriter("UserFile"); // 默认路径为根目录下

            // 核心:一边读、一边写
            char[] chars =new char[1024 *1024]; // 1MB
            int readCount =0;
            while ((readCount =fr.read(chars))!=-1){    // 读1MB的数据放到char[]数组当中
                // 边读边写入文件
                fw.write(chars,0,readCount); // 把每次写入到数组当中的数据写入文件当中
            }

            // 管道刷新
            fw.flush();
            System.out.println("管道刷新成功~");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 分开try
            // 一起try的话如果第一个发生了异常 第二个字符输出流就关闭不了
            if (fr != null) {
                try {
                    fr.close();
                    System.out.println("字符输入流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fw != null) {
                try {
                    fw.close();
                    System.out.println("字符输出流关闭成功~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

八、带有缓冲区的字符流

1、 

BufferedReader : 缓冲输入字符流 

代码演示如下: 

package com.bjpowernode.java.io;
import java.io.*;
/*
BufferedReader:
    带有缓冲区的字符输入流
    使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组,自带缓冲

public BufferedReader(Reader in) : 构造方法中Reader是一个抽象类,FileReader继承了该抽象类

BufferedReader类当中的常用方法:
    String readLine()
        读一行文字。
    // 当没有读取到任何文字的时候返回null

 */

public class BufferReaderTest01 {
    public static void main(String[] args) throws IOException {
        // 创建子类FileReader对象
        FileReader Reader =new FileReader("UserFile");
        BufferedReader br =new BufferedReader(Reader);    // 多态 父类型引用指向子类型对象 (FileReader继承了Reader该抽象类) 相当于把文件夹传了过来
        // 记住: FileReader: 节点流    BufferedReader: 包装流/处理流

        // 读取文件夹

        /*
           读一行
        String firstLine =br.readLine();
        System.out.println(firstLine);

        String secondLine =br.readLine();
        System.out.println(secondLine);
         */

        // 注意:br.readLine()方法读取一个文本行,但不带换行符(换行是因为我们输出的时候是println,ln换行)
        String s =null;
        while ((s =br.readLine())!=null){   // 当读取文件内容不是null的时候 说明有数据
            System.out.println(s);  // 输出文件内容
        }

        // 关闭流
        // 对于包装流来说,只需要关闭最外层流就可以,里面的节点流会自动关闭 (别问,问就是看过源码~)
        br.close();
    }
}

输出结果:

1.2、

 当输入字节流:FileInputStream对象的时候 怎么利用缓冲的方法读取文件 

代码演示如下:

package com.bjpowernode.java.io;
import java.io.*;

public class BufferReaderTest02 {
    public static void main(String[] args) throws IOException {
        // 字节流
        // FileInputStream fis =new FileInputStream("UserFile");

        // 通过转换流转换(InputStreamReader将字节流转换成字符流)
        // fis是节点流 reader 是包装流
        // InputStreamReader reader =new InputStreamReader(fis);

        // 这里的BufferedReader类当中的构造方法只能传一个字符流,不能传字节流
        /*
        构造方法当中Reader是一个抽象类 InputStreamReader继承了该抽象类
        所以可以把字节流先转换成字符流 然后该字符流继承了Reader抽象类 利用多态 能够传进去
         */
        // BufferedReader br =new BufferedReader(reader);
        // reader是节点流 br是包装流

        // 合并上述代码
        BufferedReader br =new BufferedReader(new InputStreamReader(new FileInputStream("UserFile")));

        // 读
        String s =null;
        while ((s=br.readLine())!=null){
            System.out.println(s);
        }

        // 关闭最外层
        br.close();
    }
}

 输出结果:

BufferedWriter: 带有缓冲的字符输出流
OutputStreamWriter:转换流

 代码演示如下:

package com.bjpowernode.java.io;
import java.io.*;

/*
BufferedWriter: 带有缓冲的字符输出流
OutputStreamWriter:转换流
 */
public class BufferedWriterTest01 {
    public static void main(String[] args) throws IOException {
        // 带有缓冲区的字符输出流
        // BufferedWriter out =new BufferedWriter(new FileWriter("copy"));
        BufferedWriter out =new BufferedWriter(new OutputStreamWriter(new FileOutputStream("copy")));   // 能个true追加

        // 开始写
        out.write("hello world");
        out.write("\n");    // 换行符
        out.write("kitty");

        // 刷新
        out.flush();
    }
}

输出结果:

九、标准输出流(掌握)

代码演示如下:

package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class PrintStreamTest01 {
    public static void main(String[] args) throws FileNotFoundException {
        // 联合起来写
        System.out.println("hello world");  // 将"hello world" 输出到控制台

        PrintStream ps =System.out; // System.out 返回的是一个PrintStream
        // 分开写
        ps.println("junker");
        ps.println("kitty");

        // 标准输出流不需要手动close()关闭

        // 我们可以改变标准输出流的输出方向吗? 可以

        // 标准输出流不再指向控制台,指向了“psFile”文件
        PrintStream printStream =new PrintStream(new FileOutputStream("psFile"));
        // 修改输出方向,将输出方向修改到“psFile”文件
        System.setOut(printStream);
        // 再输出
        System.out.println("hello world");
        System.out.println("hello kitty");

    }
}

 可以利用该标准输出流写日志【重点】

代码演示如下:

package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
日志工具
 */
public class Longer {
    // 创建一个记录日志的方法
    public static void log(String msg){ // msg代表日志信息    // 此处可以写成Object类型
        try {
            // 指向一个日志文件
            PrintStream printStream =new PrintStream(new FileOutputStream("msgFile",true)); // 追加[不会清空内容]
            // 改变输出方向
            System.setOut(printStream);

            // 日期当前时间
            Date date =new Date();
            // 格式化时间
            SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS");
            String strTime =simpleDateFormat.format(date);

            // 输出
            System.out.println(strTime +":" +msg);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

代码测试:

package com.bjpowernode.java.io;

public class RiZhiTest {
    public static void main(String[] args) {
        // 测试日志
        Longer.log("调用了Longer的方法");
        Longer.log("登录了系统注册功能");
        Longer.log("修改了密码");
        Longer.log("注册账户失败了");
    }
}

 十、File类

File
1、File类和四大家族没有关系,所以File类不能完成文件的读和写。
2、File对象代表什么?
    文件和目录路径名的抽象表示形式
    C:\Drivers这是一个File对象
    C: \Drivers\Lan\Realtek\Readme.txt也是File对象。
一个File对象有可能对应的是目录(文件夹),也可能是文件。
File只是一个路径名的抽象表示形式。
3、需要掌握File类中常用的方法

File类常用方法代码演示如下: 

package com.bjpowernode.java.io;
import java.io.File;
import java.io.IOException;


public class FileTest01 {
    public static void main(String[] args) throws IOException {
        File file =new File("D:\\file");
        //  第一种  boolean exists();
        // 判断指定的位置文件是否存在
        System.out.println(file.exists());  // false

        // 第二种:如果C:/file不存在,则以文件的形式创建出来(不是文件夹)
        // if(!file.exists()){
        //     file.createNewFile();
        // }
        // 第三种:如果C:/file不存在,则以目录(文件夹)的形式创建出来
        if (!file.exists()){
            file.mkdir();
        }

        //  第四种:可以创建多重目录(文件夹)吗 ? 比如a\b\c\d\e
        File file1 =new File("D:\\a\\b\\c\\d\\e");
        // 如果该文件不存在,那么就多重创建
        if (!file1.exists()){
            // 多重目录的形式新建
            file1.mkdirs();
        }

        //  第五种:获取文件的父路径(两种获取方式)
        File file2 =new File("D:\\java course\\day01\\HelloWorld.java");
        String s =file2.getParent();
        System.out.println(s);  // D:\java course\day01

        File f =file2.getParentFile();
        System.out.println(f);  // D:\java course\day01

        // 第六种:获取绝对路径
        File f1 =file2.getAbsoluteFile();
        System.out.println(f1); // D:\java course\day01\HelloWorld.java
    }
}
package com.bjpowernode.java.io;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
File类常用方法
 */

public class FileTest02 {
    public static void main(String[] args) {
        File file =new File("D:\\java course\\renSheng\\House.java");

        // 获取文件名
        System.out.println(file.getName()); // House.java

        // 判断是否是一个目录(文件夹)
        System.out.println(file.isDirectory()); // false

        // 判断是否是一个文件
        System.out.println(file.isFile());  // true

        // 获取文件最后一次修改的时间
        long HaoMiao =file.lastModified();  // 这个毫秒是从1970年到现在的总毫秒数
        // 如何将毫秒转化成日期?
        Date date =new Date(HaoMiao);
        // 初始化日期
        SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String s =simpleDateFormat.format(date);
        System.out.println(s);  // 2022-02-22 17:17:43 783

        // 获取文件大小
        System.out.println(file.length());  // 93   93个字节

    }
}

File中的listFile方法: 获取当前目录下的所有子文件 

代码演示如下: 

package com.bjpowernode.java.io;
import java.io.File;

// File中的listFiles方法
public class FileTest03 {
    public static void main(String[] args) {
        // File[] listFiles()方法
        // 获取当前目录(文件夹)下所有的子文件
        File file =new File("D:\\java course\\renSheng");
        File[] files=file.listFiles();

        // 对数组循环遍历
        for (File data : files){
            // 拿到绝对路径
            System.out.println(data.getAbsolutePath());
            // System.out.println(data.getName());  // 拿到名字
        }
    }
}

输出结果:

 

;