java基础14--IO流

IO流

文件

概念

一组有意义的信息集合,可以是文档、图片、程序等。在用户进行输入、输出时,以文件为基本单位。

文件流

Tips:输入流和输出流是站在内存的角度去看的,在使用中更多的是读取磁盘文件和写入磁盘文件。

  • 输入流:从磁盘文件中读取,然后写入内存中,有read方法(输入流:读磁盘,入内存)
  • 输出流:从内存中读取,向磁盘文件中写入,有write方法(输出流:读内存,入磁盘)

简记:输入流还是输出流,看内存上的操作,read方法还是write方法看磁盘上的操作,【写出,“读入”两个字】

在这里插入图片描述

常用的文件操作

创建文件

在这里插入图片描述

//new File(String pathname)
 public void creatFile01() {
        String filePath = "/Users/bijing/documents/hello.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//new File(File parent, String child)
    public void createFile02() {
        String father = "/Users/bijing/documents";
        String child = "/hello.txt";
        File file = new File(father, child);
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
获取文件的相关信息

在这里插入图片描述

public void info() {
        File file = new File("/Users/bijing/documents/haha.txt");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("文件名字:" + file.getName());
        System.out.println("文件绝对路径:" + file.getAbsolutePath());
        System.out.println("文件的父级目录:" + file.getParent());
        System.out.println("文件的大小(字节):" + file.length());
        System.out.println("文件是否存在:" + file.exists());
        System.out.println("是不是一个文件:" + file.isFile());
        System.out.println("是不是一个目录:" + file.isDirectory());
    }
目录的操作和文件删除

在这里插入图片描述

    public void fileOption() {
        String filePath = "/Users/bijing/documents/haha.txt";
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("删除成功");
            }
        } else {
            System.out.println("哈哈不存在");
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void directoryOption() {
        String filePath = "/Users/bijing/documents/haha";
        File file = new File(filePath);

        if (file.exists()) {
            if (file.delete()) {
                System.out.println("删除成功");
            }
        } else {
            System.out.println(file.getName() + "不存在");
            file.mkdirs();//mkdirs()创建多级目录,mkdir()创建一级目录
            if (file.exists()) {
                System.out.println(file.getName() + "创建成功");
            }
        }
    }
}

IO流原理及流的分类

IO流原理

在这里插入图片描述
在这里插入图片描述

流的分类

在这里插入图片描述
在这里插入图片描述

IO流体系图-常用的类

在这里插入图片描述

FileInputStream和FileOutputStream

FileInputStream实例

在这里插入图片描述

在这里插入图片描述
注意:
1. try中新建的对象,作用范围不能超过try
2. 记得用完后要close()

    //单个字节的读取,效率较低
    public void read1() {
        String path = "/Users/bijing/documents/haha.txt";
        int readData = 0;
        FileInputStream fileInputStream = null;
        try {
            //创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(path);

            //从该输入流读取一个字节的数据. 如果没有输入可用,此方法将阻止,如果返回-1,表示文件读取完毕
            while ((readData = fileInputStream.read()) != -1) {
                System.out.print((char) readData);//转成char显示
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭文件流,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //使用read(byte [] b),用字节数组去读,提高了读取的效率
    public void read2() {
        String path = "/Users/bijing/documents/haha.txt";
        int readLen = 0;
        byte[] bytes = new byte[8];//一次读取八个字节
        FileInputStream fileInputStream = null;
        try {
            //创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(path);

            // 从该输入流读取最多b.length字节的数据到字节数组. 此方法将阻塞,直到某些输入可用,
            // 如果返回-1,表示文件读取完毕
            // 如果读取正常,返回实际读取的字节数
            while ((readLen = fileInputStream.read(bytes)) != -1) {
                // 字节数组转为字符串
                System.out.print(new String(bytes, 0, readLen));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭文件流,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

FileOutputStream实例1

在这里插入图片描述
在这里插入图片描述

public void write1() {
        String path = "/Users/bijing/documents/haha.txt";
        FileOutputStream fileOutputStream = null;
        String txt = "abcdefg";
        //将字符串转成字节数组
        byte[] b = txt.getBytes();
        try {
            //构造器中如果不加true就是覆盖,加了就是追加
            fileOutputStream = new FileOutputStream(path, true);
            //写入一个字节,char可以自动转的
            fileOutputStream.write('H');
            //写入字符串
            fileOutputStream.write(b);
            //写入从start到end字符串
            fileOutputStream.write(b, 1, 5);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

FileOutputStream实例2

在这里插入图片描述

  public void copy() {
        String path1 = "/Users/bijing/documents/picture/003950-164338799031d6.jpeg";
//        String path1 = "/Users/bijing/documents/haha.txt"; 拷贝文本
        String path2 = "/Users/bijing/documents/girl.jpeg";//拷贝图片
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        byte[] b = new byte[1024];
        int readLen = 0;
        try {
            fileInputStream = new FileInputStream(path1);
            fileOutputStream = new FileOutputStream(path2);
            while ((readLen = fileInputStream.read(b)) != -1) {
                //如果是拷贝文本一定要使用这个方法,因为最后一次写入的长度不一定是1024个字节
                fileOutputStream.write(b, 0, readLen);
                //图片也可以用下面的方法
                fileOutputStream.write(b);
            }

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

FileReader和FileWriter

在这里插入图片描述
注意:FileWriter使用后,必须关闭或者刷新,否则还在内存中并没有写入文件中
在这里插入图片描述
简记:输入流还是输出流,看内存上的操作,read方法还是write方法看磁盘上的操作

FileReader案例

public void read1() {
        String path = "/Users/bijing/documents/hello.txt";
        FileReader fileReader = null;
        int len = 0;
        char[] chars = new char[1024];
        try {
            fileReader = new FileReader(path);
            while ((len = fileReader.read(chars)) != -1) {
                System.out.print(new String(chars, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (IOException e) {

                }
            }
        }
     } 

FileWriter案例

在这里插入图片描述

 public void write() {
        String path = "/Users/bijing/documents/note.txt";
        FileWriter fileWriter = null;
        String s = "风雨之后,定见彩虹";
        try {
            fileWriter = new FileWriter(path);
            //加true就是追加,不加true就是覆盖
            fileWriter = new FileWriter(path, true);
            fileWriter.write(s);
//            fileWriter.write('H');
//            fileWriter.write("hello");
//            fileWriter.write("hello", 0, s.length());
//            fileWriter.write(new char[]{'1', 'a', '3'}, 0, s.length());            
            
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileWriter != null) {
                try {
                    //一定要关闭或者刷新,否则还在内存中,没有写入到文件中
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

节点流和处理流

介绍

在这里插入图片描述

下图是节点流,数据源可以是一个文件,也可以是一个数组,管道。
在这里插入图片描述

下图是处理流也叫包装流,以BufferedReader为例,它有个属性Reader,所以构造器中可以传任意Reader子类(字节流类似)对其进行操作
在这里插入图片描述

节点流和处理流的区别和联系

在这里插入图片描述

模拟修饰器模式

Reader_.java

public abstract class Reader_ {
    //把Reader_做成一个私有属性,它有子类FileReader_和StringReader_
    private Reader_ in;

    public void readFile() {
    }

    public void readString() {
    }
}


Reader_.java的子类,FileReader_

public class FileReader_ extends Reader_ {

    public void readFile() {
        System.out.println("对文件进行读取...");
    }
}

Reader_.java的子类,StringReader_

public class StringReader_ extends Reader_ {

    public void readString() {
        System.out.println("对字符串进行读取...");
    }

}

包装流中的缓冲流BufferedReader_也要继承Reader_,在这个缓冲流中可以封装对节点流的一些列操作

public class BufferedReader_ extends Reader_ {
    //这里的in可以根据构造器中传入的类型(Reader的子类),在后面对用相应的方法,同时还可以对节点流的方法进行一些额外的封装
    private Reader_ in;

    public BufferedReader_(Reader_ in) {
        this.in = in;
    }

    public void readFiles(int num) {
        for (int i = 0; i < num; i++) {
            in.readFile();
        }
    }

    public void readStrings(int num) {
        for (int i = 0; i < num; i++) {
            in.readString();
        }
    }
}

Test.java,构造器中传入了什么样的节点流就可以使用它的方法,同时也可以使用特有的,对节点流中方法进行封装过的方法

public class Test {
    public static void main(String[] args) {
        BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_());
        bufferedReader_.readFiles(10);
        BufferedReader_ bufferedReader_1 = new BufferedReader_(new StringReader_());
        bufferedReader_1.readStrings(10);
    }
}

BufferedReader和BufferedWriter

注意:如果缓冲区没满时使用close方法不会自动的朝目标文件进行读或写,此时需要flush()方法

在这里插入图片描述

BufferedReader案例(按行读取)

在这里插入图片描述

public class BufferedReader_ {
    public static void main(String[] args) throws IOException {
        String path = "/Users/bijing/documents/hello.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
        String line;//按行读取,效率高
        //bufferedReader.readLine()是按行读取文件,当返回null时代表已经读取到文件的末尾
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }
        bufferedReader.close();
    }
}
BufferedWriter案例

在这里插入图片描述
注意:一般都要加上 bufferedWriter.newLine()用来另起一行输入

public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {
        String s = "韩顺平教育";
        String path = "/Users/bijing/documents/note.txt";
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path));
//        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path),true); //追加
        bufferedWriter.write("hello," + s);
        bufferedWriter.newLine();//表示插入一个和系统相关的换行符
        bufferedWriter.write("hello1," + s);
        bufferedWriter.newLine();//表示插入一个和系统相关的换行符
        bufferedWriter.write("hello2," + s);
        bufferedWriter.newLine();//表示插入一个和系统相关的换行符
        bufferedWriter.close();

    }
}

文本拷贝案例

在这里插入图片描述

    //注意:
    //BufferedReader和BufferedWriter都是按照字符进行操作
    //如果用来操作二进制文件可能会造成破坏(如音频,照片,视频)
public class BufferedCopy {
    public static void main(String[] args) throws IOException {
        String path1 = "/Users/bijing/documents/hello.txt";
        String path2 = "/Users/bijing/documents/heihei.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(path1));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path2));
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            bufferedWriter.write(line);
            bufferedWriter.newLine();
        }
        bufferedReader.close();
        bufferedWriter.close();
    }
}

BufferedInputStream和BufferedOutputStream

在这里插入图片描述
BufferedInputStream具有InputStream属性,所以构造器中可以传入InputStream的子类

…和上面的类似(但是它既可以处理字节流也可处理字符流)

对象处理流ObjectInputStream和ObjectOutputStream

在这里插入图片描述

在这里插入图片描述

ObjectOutputStream序列化案例

注意:序列化对象必须要实现Serializable接口或Externalizable接口
在这里插入图片描述

public class ObjectOutputStream_ {
    public static void main(String[] args) {
        String path = "/Users/bijing/documents/object.dat";
        try {
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(path));
            //序列化数据到object.dat
            objectOutputStream.writeInt(100);
            objectOutputStream.writeBoolean(true);
            objectOutputStream.writeUTF("放字符串不是用String,用UTF");
            objectOutputStream.writeObject(new Dog("小明", 8));
            objectOutputStream.close();

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

Dog.java


public class Dog implements Serializable {
    private String name;
    private int age;
    
    //serialVersionUID 序列化的版本号,可以提高兼容性
    private static final long serialVersionUID = 1L;
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

ObjectInputStream反序列化案例

注意:反序列化的顺序必须和序列化的顺序一致
在这里插入图片描述

public class ObjectInputStream_ {
    public static void main(String[] args) throws Exception, ClassCastException {
        String path = "/Users/bijing/documents/object.dat";
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(path));
        //这边反序列化(读),要求和序列化的顺序一致
        System.out.println(objectInputStream.readInt());
        System.out.println(objectInputStream.readBoolean());
        System.out.println(objectInputStream.readUTF());
        Object dog = objectInputStream.readObject();
        System.out.println(dog);
        System.out.println(((Dog) dog).getName());
        objectInputStream.close();
    }

}

对象处理流的注意事项(3,4,5)

在这里插入图片描述

标准输入输出流

在这里插入图片描述

public class InputAndOutput {
    public static void main(String[] args) {
        //System类的public final static InputStream in = null;
        //System.in的编译类型    InputStream
        //System.in的运行类型    BufferedInputStream
        System.out.println(System.in.getClass());

        //System.out  public final static PrintStream out = null;
        //编译类型:PrintStream
        //运行类型:PrintStream
        //标准输出,显示器
    }
}

转换流InputStreamReader和OutStreamWriter

在这里插入图片描述
CodeQuestion.java

public class CodeQuestion {
    public static void main(String[] args) throws IOException {
        String path = "/Users/bijing/documents/hello3.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }
        bufferedReader.close();
    }
}

这个hello3.txt我们是用gbk编码保存的,这边直接用处理流形式的字符流去读取会出现乱码情况,由此引出InputStreamReader,它的构造器中传入字节流,指定编码方式,然后将它当做InputReader子类,传入BufferedInputReader中使用就可以避免乱码

InputStreamReader_.java

public class InputStreamReader_ {


    public static void main(String[] args) throws IOException {
        String path = "/Users/bijing/documents/hello3.txt";
        //把FileInputStream转成了InputStreamReader,指定了编码gbk
        InputStreamReader isr = new InputStreamReader(new FileInputStream(path), "gbk");
        //把FileInputStream传给BufferedReader
        BufferedReader bufferedReader = new BufferedReader(isr);
        String s;
        while ((s = bufferedReader.readLine()) != null) {
            System.out.println(s);
        }
    }
}

案例

在这里插入图片描述

public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {
        String path = "/Users/bijing/documents/hello3.txt";
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(path), "gbk");
        outputStreamWriter.write("明天你好");
//        注释是使用了处理流,如果和上面同时使用,outputStreamWriter.write("明天你好");就不要了,否则也会写入,
//        同时outputStreamWriter.close();不要了,因为它关闭了,bufferedWriter.close();会报错 
//        BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
//        bufferedWriter.write("明天会更好");
        outputStreamWriter.close();
//        bufferedWriter.close();
    }
}

打印流PrintStream和PrintWriter(一个是打印字节一个是打印 字符)

在这里插入图片描述

字节打印流

public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        //System.out的编译类型是PrintStream,默认的情况PrintScream输出数据的位置是标准输出,即显示器
        PrintStream out = System.out;
        out.print("你好China");
        //print的底层就是write
        out.write("明天你好".getBytes());
        out.close();
//        可以修改打印流的位置
        System.setOut(new PrintStream("/Users/bijing/documents/hello.txt"));
        System.out.print("java好难学哈哈");

    }
}

字符打印流
在这里插入图片描述

public class PrintWriter_ {
    public static void main(String[] args) throws IOException {
        //PrintWriter的构造器中可以指定输出的位置
//        PrintWriter printWriter = new PrintWriter(System.out);
//        PrintWriter printWriter = new PrintWriter(new FileWriter("/Users/bijing/documents/hello3.txt"));
//        PrintWriter printWriter = new PrintWriter("/Users/bijing/documents/hello.txt");
//      也可以直接指定位置,指定编码进行输入
        PrintWriter printWriter = new PrintWriter("/Users/bijing/documents/hello3.txt", "gbk");
        printWriter.println("我是大聪明a");
        printWriter.close();
    }
}

Properties类

在这里插入图片描述

传统方法

public class Properties_ {
    public static void main(String[] args) throws IOException {
//        String path = "/Users/bijing/Documents/study/java/space/IO_scream/src/mysql.properties";
        String path = "./src/mysql.properties";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            String[] s = line.split("=");
            System.out.println(s[0] + ":" + s[1]);
        }
        bufferedReader.close();

    }
}

Properties类基本介绍

在这里插入图片描述

Properties类的常用方法

这边的设备可以是指定的流对象
在这里插入图片描述

案例:读取

在这里插入图片描述

public class Properties02 {
    public static void main(String[] args) throws IOException {
        //使用Properties类读取mysql.properties文件
        //1.创建一个Properties对象
        Properties properties = new Properties();
        //2.加载指定配置文件
        properties.load(new FileReader("./src/mysql.properties"));
        //3.把key-value显示到控制台
        properties.list(System.out);
        //4.根据key获取对应的值
        System.out.println(properties.get("user"));
    }
}

案例:添加和修改

public class Properties03 {
    public static void main(String[] args) throws IOException {
        Properties p = new Properties();
        //如果key没有,就是新建
        p.setProperty("姓名:", "张三");
        p.setProperty("年龄:", "40");
        //如果key有就是修改
        p.setProperty("姓名:", "李四");

        //这个null是添加注释
        p.store(new FileOutputStream("./src/mysql2.properties"), null);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值