流的分类

  1. 按方向
  • 输入流:存储设备->内存
  • 输出流:内存->存储设备
  1. 按单位

    • 字节流:以字节为单位,可以读写所有数据
    • 字符流:以字符为单位,只能读写文本数据(一个字符可能有好几个字节)
  2. 按功能

    • 节点流:具有实际传输数据的读写功能
    • 过滤流:在节点流的基础之上增强功能

字节流

InputStream

OutputStream


文件字节流

FileInputStream

  1. 一个字节一个字节地读取

    //1.指定文件路径
    FileInputStream fis = new FileInputStream("E:\\test.txt");
    
    //2.一个字节一个字节地读取数据
    int data=0;
    while((data=fis.read())!=-1){
     System.out.print((char)data);
    }
    
    //3.关闭
    fis.close();
  2. 一次读取多个字节

    //1.指定文件路径
    FileInputStream fis = new FileInputStream("E:\\test.txt");
    
    //2.一次读取多个字节长度
    int len = 0;
    byte[] buf = new byte[4];
    while((len=fis.read(buf))!=-1){
     System.out.print(new String(buf,0,len));
    }
    
    //3.关闭
    fis.close();

FileOutputStream

需要将字符串转为字节流再写入文件

getBytes()

FileOutputStream构造方法的第二个参数为true,则再文件末尾接着写入(不覆盖原有数据)

// 1. 指定文件路径
        FileOutputStream fos = new FileOutputStream("E:\\a.txt");
        //FileOutputStream fos = new FileOutputStream("E:\\a.txt",true);

        // 2. 写入数据
        fos.write(97);      //写入字符‘a’
        fos.write('b');     //写入字符‘b’

        String str = "Hello FileOutputStream";
        fos.write(str.getBytes());      //将字符串转为字节流写入文件


        // 3. 关闭
        fos.close();

案例:实现文件复制

// 1.文件字节输入
        FileInputStream fis = new FileInputStream("E:\\photos\\head.jpg");
        // 2.文件字节输出
        FileOutputStream fos = new FileOutputStream("E:\\head.txt");

        // 3.读写
        byte[] buf = new byte[1024];
        int count = 0;
        while((count = fis.read(buf))!=-1){
            fos.write(buf,0,count);
        }

        // 4.关闭
        fos.close();
        fis.close();

字节缓冲流

提高读取效率

BufferedInputStream

//1.创建BufferedInputStream
        FileInputStream fis = new FileInputStream("E:\\test.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);

        //2.读取
        int data = 0;
        while((data=bis.read())!=-1){
            System.out.print((char)data);
        }

        //3.关闭  关闭BufferedInputStream会自动关闭FileInputStream
        bis.close();

BufferedOutputStream

先写到缓冲区,再写入内存设备

//1.创建BufferedOutputStream
        FileOutputStream fos = new FileOutputStream("E:\\test.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //2.写入缓冲区(缓冲区大小:8K)
        for(int i=0;i<10;++i){
            bos.write("hellow BufferedOutputStream\n".getBytes());
        }
        //3.写入硬盘
        bos.flush();

        //4.关闭
        bos.close();

对象流

使用流传输对象的过程称为序列化、反序列化

注意事项:

  • 被序列化的类必须实现Serializable接口
  • 被序列化的类中的对象属性也必须实现Serializable接口
  • 使用transient修饰的属性将不会被序列化,反序列化时该属性被赋值为默认值
  • 静态属性不能被序列化
  • 序列化多个对象可以使用集合
  • 序列化版本号ID用于保证序列化和反序列化的类是同一个类

被序列化的类实现如下:

//实现Serializable接口才可序列化
public class Student implements Serializable {

    //序列化版本号ID
    private static final long serialVersionUID = 100L;

    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }


    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

ObjectOutputStream

序列化

FileOutputStream fos = new FileOutputStream("E:\\student.dat");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        Student s1 = new Student("Jack",17);
        oos.writeObject(s1);

        oos.close();

ObjectInputStream

反序列化

FileInputStream fis = new FileInputStream("E:\\student.dat");
        ObjectInputStream ois = new ObjectInputStream(fis);

        Student s1 = (Student)ois.readObject();

        ois.close();

        System.out.println(s1);

字符流


仅能读写文本文件

Reader

Writer

文件字符流

类比文件字节流

FileReader

  1. 一次读取一个字符

    FileReader fr = new FileReader("E:\\test.txt");
    
    int data = 0;
    while((data=fr.read())!=-1){
     System.out.print((char)data);
    }
    
    fr.close();
  2. 一次读取多个字符

    FileReader fr = new FileReader("E:\\test.txt");
    
    char[] buf = new char[1024];
    int count = 0;
    while((count=fr.read(buf))!=-1){
     System.out.print(new String(buf,0,count));
    }
    
    fr.close();

FileWriter

FileWriter fw = new FileWriter("E:\\test.txt");

        fw.write("你好");
        fw.flush();         //刷新

        fw.close();

案例:实现文件复制

只能复制文本文件

FileReader fr = new FileReader("E:\\test.txt");
        FileWriter fw = new FileWriter("E:\\hhh.txt");

        char[] buf = new char[1024];
        int count = 0;
        while((count=fr.read(buf))!=-1){
            fw.write(buf,0,count);
            fw.flush();
        }

        fw.close();
        fr.close();

字符缓冲流

BufferedReader

FileReader fr = new FileReader("E:\\test.txt");
        BufferedReader br = new BufferedReader(fr);

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

        br.close();

BufferedWriter

FileWriter fw = new FileWriter("E:\\test.txt");
        BufferedWriter bw = new BufferedWriter(fw);

        for (int i=0;i<10;++i) {
            bw.write("Hello BufferedWriter and BufferedReader");
            bw.newLine();       //换行
            bw.flush();         //将缓存写入文件
        }

        bw.close();

PrintWriter

PrintWriter pw = new PrintWriter("E:\\test.txt");

        pw.println(97);     //打印数字
        pw.println(4.556);
        pw.println('a');    //打印字符
        pw.println("hello world");//打印字符串

        pw.close();

转换流

字节流与字符流转换

InputStreamReader

是字节流通向字符流的桥梁

// 以utf-8编码方式读取
        FileInputStream fis = new FileInputStream("E:\\test.txt");
        InputStreamReader isr = new InputStreamReader(fis,"utf-8");

        int data = 0;
        while((data=isr.read())!=-1){
            System.out.print((char)data);
        }

        isr.close();

OutputStreamWriter

是字符流通向字节流的桥梁

FileOutputStream fos = new FileOutputStream("E:\\test.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");

        for (int i = 0; i < 10; i++) {
            osw.write("hello\n");
        }

        osw.close();

File类

代表物理盘符中的一个文件或文件夹

分隔符

  • 路径分隔符:;
  • 名称分隔符:\

    System.out.println("路径分隔符:"+ File.pathSeparator);
            System.out.println("名称分隔符:"+ File.separator);

文件操作

// 1.创建文件对象
        File file = new File("E:\\file.txt");
        System.out.println(file.toString());        //打印文件路径

        // 2.创建文件
        if(!file.exists()){
            boolean b = file.createNewFile();
            System.out.println("创建结果:"+b);
        }

        // 3.删除文件
        /// 3.1 直接删除
        //file.delete();  //返回boolean
        /// 3.2 JVM退出时删除
        file.deleteOnExit();
        Thread.sleep(3000);     //休眠3秒便于观察

        // 4.获取文件信息
        System.out.println(file.getAbsoluteFile()); //绝对路径
        System.out.println(file.getPath());         //获取创建文件对象时输入的路径
        System.out.println(file.getName());         //获取文件名
        System.out.println(file.getParent());       //父级名称
        System.out.println(file.length());          //文件长度
        System.out.println(new Date(file.lastModified()).toLocaleString());//创建时间

        // 5.判断
        System.out.println(file.canWrite());        //是否可写
        System.out.println(file.isFile());          //是否是文件
        System.out.println(file.isHidden());        //是否隐藏

文件夹操作

delete()只能删除空文件夹(文件夹中不能有文件夹或者文件)

// 1. 创建文件夹对象
        File dir = new File("E:\\test\\demo");

        // 2. 创建文件夹
        if(!dir.exists()){
            //dir.mkdir();      //创建单级目录
            System.out.println("创建结果:" + dir.mkdirs());       //创建多级目录
        }

        // 3. 删除文件夹     只能删除最底层的一级目录,而且该目录下不能有文件
        /// 3.1 直接删除
        //dir.delete();
        /// 3.2 JVM关闭时删除
        dir.deleteOnExit();
        //Thread.sleep(3000);

        // 4. 获取文件夹信息
        System.out.println(dir.getAbsolutePath());      //绝对路径
        System.out.println(dir.getPath());              //获取创建文件夹对象时输入的路径
        System.out.println(dir.getName());              //文件夹名称
        System.out.println(dir.getParent());            //父级目录
        System.out.println(new Date(dir.lastModified()).toLocaleString());//创建时间

        // 5. 判断
        System.out.println(dir.isDirectory());          //是否是文件夹
        System.out.println(dir.isHidden());             //是否隐藏

        // 6. 遍历文件夹
        File dir2 = new File("E://photos");
        String[] filesName = dir2.list();
        for(String str:filesName){
            System.out.println(str);
        }

FileFilter接口

实现FileFilter接口的accept方法可以实现对文件/文件夹的过滤

例:打印E:photos下的所有jpg文件

File dir2 = new File("E://photos");
        File[] files = dir2.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if(pathname.getName().endsWith("jpg")){
                    return true;
                }
                return false;
            }
        });

        for(File file : files){
            System.out.println(file.getName());
        }

案例1:递归遍历文件夹

public static void listDir(File dir){
        File[] files = dir.listFiles();
        if(files!=null && files.length>0){
            for(File file : files){
                if(file.isDirectory()){     //如果是文件夹,则递归遍历
                    listDir(file);
                }
                else{
                    System.out.println(file.getAbsolutePath());
                }
            }
        }
        else{
            System.out.println("文件夹不存在或者为空文件夹");
        }
    }

案例2:递归删除文件夹

先删除文件夹中的文件再删除文件夹

public static void deleteDir(File dir){
        File[] files = dir.listFiles();
        if(files==null){
            System.out.println("文件夹不存在");
            return;
        }

        if(files.length>0){
            for(File file : files){
                if(file.isDirectory()){
                    deleteDir(file);
                }
                else{           //如果是文件,则直接删除
                    System.out.println("删除文件:"+file.getAbsolutePath()+" : "+file.delete());
                }
            }
        }
        //删除文件夹
        System.out.println("删除文件夹:"+dir.getAbsolutePath()+" : "+dir.delete());

    }

Properties属性集合

特点:

  • 存储属性名和属性值
  • 属性名和属性值都是字符串类型
  • 和流有关
  • 线程安全

Properties集合的基本使用

// 1.创建集合
        Properties properties = new Properties();

        // 2.添加数据
        properties.setProperty("username","Jack");
        properties.setProperty("age","21");
        System.out.println(properties);

        // 3.遍历
        //可以使用keySet entrySet StringPropertyNames()遍历
        Set<String> pronames = properties.stringPropertyNames();
        for(String str:pronames){
            System.out.println(str + " == "+properties.getProperty(str));
        }

Properties集合与流有关的方法

  • list方法
  • store方法
  • load方法
// list 列表
        PrintWriter pw = new PrintWriter("E:\\print.txt");
        properties.list(pw);
        pw.close();

        // store 保存
        FileOutputStream fos = new FileOutputStream("E:\\print.properties");
        properties.store(fos,"这里是注释");
        fos.close();

        // load 加载
        Properties properties2 = new Properties();
        FileInputStream fis = new FileInputStream("E:\\print.properties");
        properties2.load(fis);
        fis.close();
        System.out.println(properties2);