JAVA学习笔记—IO流

I/O 框架

流的概念

  • 内存与存储设备之间传输数据的通道

水(相当于数据)-> 传输水的管道(相当于流)-> 脸盆(相当于内存)

生活用水 -> 流入

家庭废水 -> 流出

流的分类

按方向【重点】

  • 输入流:将<存储设备>中的内容读到<内存>中
  • 输出流:将<内存>中的内容写到<存储设备>中

按单位

  • 字节流:以字节为单位,可以读写所有数据
  • 字符流:以字符为单位,只能读写文本数据

按功能

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

字节流

字节流的父类(抽象类)

//InputStream 字节输入流
public int read(){
    
    }
public int read(byte[] b){
    
    }
public int read(byte[] b, int off, int len){
    
    }

// OutputStream 字节输出流
public void write(int n){
    
    }
public void write(byte[] b){
    
    }
public void write(byte[] b, int off, int len){
    
    }

文件字节流

文件输入流

//文件字节输入流
public static void main(String[] args) throws Exception{
    
    
    //1. 创建FileInputStream,并指定文件路径
    FileInputStream file = new FileInputStream("路径/a.txt");
    //2. 读取文件
    //2.1 单字节读取
    int data = 0;
    while((data=file.read())!=-1){
    
    
        System.out.print((char) data);
    }
    //2.2.1 一次读取多个字节
    byte[] buf = new byte[3];
    int count = file.read(buf);
    System.out.println(new String(buf));
    System.out.println(count);
    int count2 = file.read(buf);
    System.out.println(new String(buf));
    System.out.println(count2);
   
    //2.2.1 一次读取多个字节
    byte[] buf = new byte[1024];
    int count = 0;
    while ((count=file.read(buf))!=-1){
    
    
        System.out.println(new String(buf,0,count));
    }
    //3. 关闭
    file.close();
    System.out.println("\n执行完毕");
}

文件输出流

//FileOutputStream
public static void main(String[] args) throws Exception{
    
    
    //1. 创建FileOutputStream,并指定文件路径
    FileOutputStream fos = new FileOutputStream("路径/b.txt",true);
  	//true 不覆盖
    //2. 输出文件
    fos.write(97);
    fos.write('b');
    fos.write('c');
    String str = "helloworld";
    fos.write(str.getBytes());
    //3. 关闭
    fos.close();
    System.out.println("执行完毕");
}

图片复制案例

public static void main(String[] args) throws Exception {
    
    
    //使用文件字节流实现文件的复制
    // 1 创建流
    // 1.1 文件字节输入流
    FileInputStream fis = new FileInputStream("路径/a.jpg");
    // 1.2 文件字节输出流
    FileOutputStream fos = new FileOutputStream("路径/b.jpg");
    // 2 边读边写
    byte[] buf = new byte[1024];
    int count = 0;
    while((count=fis.read(buf))!=-1){
    
    
        fos.write(buf,0,count);
    }
    // 3 关闭
    fis.close();
    fos.close();
}

字节缓冲流

缓冲流:BufferedInputStream/ BufferedOutputStream

  • 提高IO效率,减少访问磁盘次数
  • 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close
    //BufferedInputStream
    public static void main(String[] args) throws Exception{
    
    
        //1. 创建BufferedInputStream
        FileInputStream fis = new FileInputStream("路径/a.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
        //2. 读取
        int data = 0;
        while((data=bis.read())!=-1){
    
    
            System.out.print((char)data);
        }
        //自己创建缓冲区
        byte[] buf = new byte[1024];
        int count = 0;
        while((count=bis.read(buf))!=-1){
    
    
            System.out.println(new String(buf,0,count));
        }
        //3. 关闭
        bis.close();
        System.out.println("\n执行完毕");
    }
public static void main(String[] args) throws Exception{
    
    
    //1. 创建BufferedOutputStream 字节输出缓冲流
    FileOutputStream fos = new FileOutputStream("路径/b2.txt");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    //2. 写入文件
    for(int i=0;i<10;i++){
    
    
        bos.write("helloworld\n".getBytes());//写入缓冲区,没超过8K缓冲区
        bos.flush();//刷新到硬盘
    }
    //3. 关闭
    bos.close();
    System.out.println("\n执行完毕");
}

对象流

  • 增强了缓冲区功能
  • 增强了读写8种基本数据类型和字符串的功能
  • 增强了读写对象的功能
    • readObject() 从流中读取一个对象
    • writeObject(Object obj) 向流中写入一个对象

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

序列化与反序列化

序列化

  • 序列化类必须要实现Serializable接口
//实现接口 标记接口
public class Student implements Serializable {
    
    }

//使用ObjectOutputStream 实现对象的序列化
public static void main(String[] args) throws Exception{
    
    
        //1. 创建对象流
        FileOutputStream fos = new FileOutputStream("路径/stu.bin");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        //2. 序列化(写入操作)
        Student s1 = new Student("zhangsan",20);
        oos.writeObject(s1);
        //3. 关闭
        oos.close();
        System.out.println("执行完毕");
}

反序列化

// 使用ObjectInputSteam实现反序列化(读取重构对象)
public static void main(String[] args) throws Exception{
    
    
        //1. 创建对象流
        FileInputStream fis = new FileInputStream("路径/stu.bin");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //2. 读取文件(反序列化)
        Student s = (Student) ois.readObject();
        //关闭
        ois.close();
        System.out.println("执行完毕");
        System.out.println(s.toString());//Student{name='zhangsan', age=20}
}

注意事项

  1. 某个类要想序列化必须实现Serializable接口
  2. 序列化类中对象属性要求实现Serializable接口
  3. 序列化版本号ID,保证序列化的类和反序列化的类是同一个类
  4. 使用transient(瞬间的)修饰属性,这个属性就不能序列化
  5. 静态属性不能序列化
  6. 序列化多个对象,可以借助集合来实现

具体的序列化过程是这样的:

​ 序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。

//序列化多个对象,可以借助集合来实现
//2. 序列化(写入操作)
Student s1 = new Student("zhangsan",20);
Student s2 = new Student("lisi",25);
ArrayList<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
oos.writeObject(list);

//2. 读取文件(反序列化)
//Student s = (Student) ois.readObject();
ArrayList<Student> list = (ArrayList<Student>) ois.readObject();
//关闭
ois.close();
System.out.println("执行完毕");
System.out.println(list.toString());
//[Student{name='zhangsan', age=0}, Student{name='lisi', age=0}]

编码方式

  • ISO-8859-1 收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号
  • UTF-8 针对Unicode码表的可变长度字符编码
  • GB2312 简体中文
  • GBK 简体中文、扩充
  • BIG5 台湾,繁体中文

字符流

public static void main(String[] args) throws Exception{
    
    
    //1. 创建FileInputStream对象
    FileInputStream fis = new FileInputStream("路径/hello.txt");
    //2. 读取
    int data = 0;
    while((data = fis.read())!=-1){
    
    
        System.out.print((char)data);
    }
    //3. 关闭
    fis.close();
}

字符流的父类(抽象类)

reader 字符输入流

  • public int read(){}
  • public int read(char[] c){}
  • public int read(char[] b, int off, int len){}

Writer 字符输出流

  • public void write(int n){}
  • public void write(String str){}
  • public void write(char[] c){}
//使用FileReader读取文件
public static void main(String[] args) throws Exception {
    
    
    //1. 创建FileReader 文件字符输入流
    FileReader fr = new FileReader("路径/hello.txt");
    //2. 读取
    //2.1 单个字符读取
    /*
    int data = 0;
    while ((data = fr.read()) != -1) {
        System.out.print((char) data);
    }

     */
    //2.2 字符缓冲区
    char[] buf = new char[1024];
    int count = 0;
    while((count=fr.read(buf))!=-1){
    
    
        System.out.println(new String(buf,0,count));
    }
  	//3. 关闭
    fr.close();
    System.out.println("执行完毕");
}
//使用FileWriter读取文件
public static void main(String[] args) throws Exception {
    
    
        //1. 创建FileWriter对象
        FileWriter fw = new FileWriter("/Users/xay/Desktop/编程/JAVA-FullStack/JavaSE/JavaBasics/src/Demo15/write.txt");
        //2. 写入
        for (int i = 0; i < 10; i++) {
    
    
            fw.write("java是世界上最好的语言\n");
            fw.flush();
        }
        //3. 关闭
        fw.close();
        System.out.println("执行完毕");
}

字符流案例(使用上述内容复制文本)

  • 不能复制图片或二进制文件,使用字节流可以复制任意文件
  • 使用字节流可以复制任何文件
  • 字符流可以复制文本文件
public static void main(String[] args) throws Exception {
    
    
    //1. 创建FileReader FileWriter
    FileReader fr = new FileReader("路径/write.txt");
    FileWriter fw = new FileWriter("路径/write2.txt");
    //2. 读写
    int data = 0;
    while((data=fr.read())!=-1){
    
    
        fw.write(data);
        fw.flush();
    }
    //3. 关闭
    fr.close();
    fw.close();
    System.out.println("执行完毕");
}

字符缓冲流

BufferedReader / BufferedWriter

高效读写、支持输入换行符、可一次写一行读一行

//BufferedReader 使用字符缓冲流读取文件
public static void main(String[] args) throws Exception{
    
    
    //创建缓冲流
    FileReader fr = new FileReader("路径/write.txt");
    BufferedReader br = new BufferedReader(fr);
    //2. 读取
    //2.1 第一种方式
    char[] buf = new char[1024];
    int count = 0;
    while((count=br.read(buf))!=-1){
    
    
        System.out.print(new String(buf,0,count));
    }
    //2.2 第二种方式,一行一行读取
    String line = null;
    while((line = br.readLine())!=null){
    
    
        System.out.println(line);
    }
    //3. 关闭
    br.close();
    System.out.println("执行结束");
}
//BufferedWriter 使用字符缓冲流写入文件
public static void main(String[] args) throws Exception{
    
    
    //1. 创建BufferedWriter对象
    FileWriter fw = new FileWriter("路径/buffer.txt");
    BufferedWriter bw = new BufferedWriter(fw);
    //2. 写入
    for(int i=0;i<10;i++){
    
    
        bw.write("好好学习,天天向上");
        bw.newLine();//换行符
        bw.flush();
    }
    //3. 关闭
    bw.close();
    System.out.println("执行完毕");
}

PrintWriter

  • 封装了print() / println() 方法 支持写入后换行
  • 支持数据原样打印
//PrintWriter 的使用
public static void main(String[] args) throws Exception {
    
    
    //1. 创建打印流
    PrintWriter pw = new PrintWriter("路径/print.txt");
    //2. 打印
    pw.println(97);//97
    pw.println(true);//true
    pw.println(3.14);//3.14
    pw.println('a');//a
    //3. 关闭
    pw.close();
    System.out.println("执行结束");
}

转换流

  • 桥转换流 InputStreamReader / OutputStreamWriter
  • 可将字节流转换为字符流
  • 可设置字符的编码方式
//InputStreamReader 的使用 读取文件,指定使用的编码
public static void main(String[] args) throws Exception {
    
    
    //1. 创建InputStreamReader 对象
    FileInputStream fis = new FileInputStream("路径/write.txt");
    InputStreamReader isr = new InputStreamReader(fis,"utf-8");
    //2. 读取文件
    int data = 0;
    while((data=isr.read())!=-1){
    
    
        System.out.print((char)data);
    }
    //3. 关闭
    isr.close();
    System.out.println("执行完毕");
}
//OutputStreamWriter 写入文件,使用指定编码
public static void main(String[] args) throws Exception {
    
    
    //1. 创建OutputStreamWriter对象
    FileOutputStream fos = new FileOutputStream("路径/info.txt");
    OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
    //2. 写入
    for (int i = 0; i < 10; i++) {
    
    
        osw.write("你好中国");
        osw.flush();
    }
    //3. 关闭
    osw.close();
    System.out.println("执行成功");
}

File类

概念:代表物理盘符中的一个文件或者文件夹

File类的使用

  1. 分隔符
  2. 文件操作
  3. 文件夹操作

FileFilter接口

  • public interface FileFilter
    • boolean accept(File pathname)
  • 当调用File类中的listFiles( )方法时,支持传入FileFIlter接口实现类,对获取文件进行过滤,只有满足条件的文件的才可以出现在listFiles( )的返回值中
public class Demo01 {
    
    
    /*
File类的使用
    1. 分隔符
    2. 文件操作
    3. 文件夹操作
    */
    public static void main(String[] args) throws Exception {
    
    
        separator();
        fileOpe();
        directoryOpe();
    }

    // 1. 分隔符
    public static void separator() {
    
    
        System.out.println("路径分隔符" + File.pathSeparator);//:
        System.out.println("名称分隔符" + File.separator);///
    }

    // 2. 文件操作
    public static void fileOpe() throws Exception {
    
    
        // 1. 创建文件
        File file = new File("路径/file.txt");
        System.out.println(file.toString());
        if (!file.exists()) {
    
    
            boolean b = file.createNewFile();
            System.out.println("创建结果:" + b);//创建结果:true
        }
        // 2. 删除文件
        // 2.1 直接删除
        //System.out.println("删除的结果:" + file.delete());
        // 2.2 使用jvm退出时删除
        //ile.deleteOnExit();
        //Thread.sleep(5000);
        // 3. 获取文件信息
        System.out.println("获取绝对路径:" + file.getAbsolutePath());
        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());

        // 4. 判断
        System.out.println("是否可写:" + file.canWrite());
        System.out.println("是否是文件:" + file.isFile());
        System.out.println("是否隐藏:" + file.isHidden());
    }

    // 3. 文件夹操作
    public static void directoryOpe() throws Exception {
    
    
        // 1. 创建文件夹
        File dir = new File("路径/a/b/c");
        System.out.println(dir.toString());
        if (!dir.exists()) {
    
    
            //dir.mkdir();//只能创建单级目录
            boolean b = dir.mkdirs();//创建多级目录
            System.out.println("创建结果:" + b);
        }
        // 2. 删除文件夹
        // 2.1 直接删除
        //System.out.println("删除结果:"+dir.delete());// 只能删除最底层空目录
        // 2.2 使用jvm删除
        //dir.deleteOnExit();

        // 3. 获取文件夹信息
        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());

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

        // 5. 遍历文件夹
        File dir2 = new File("路径/Demo16");
        String[] files = dir2.list();
        for(String file :files){
    
    
            System.out.println(file.toString());
        }

        // FileFilter接口的使用
        File[] files2 = dir2.listFiles(new FileFilter() {
    
    
            @Override
            public boolean accept(File pathname) {
    
    
                if(pathname.getName().endsWith(".txt")){
    
    
                    return true;
                }
                return false;
            }
        });
        for(File file : files2){
    
    
            System.out.println(file.getName());
        }
    }
}

递归遍历文件夹

//递归遍历文件夹
public static void main(String[] args) throws Exception {
    
    
    listDir(new File("/Users/xay/Desktop/编程/JAVA-FullStack/JavaSE/JavaBasics/src"));
}

public static void listDir(File dir) {
    
    
    File[] files = dir.listFiles();
    System.out.println(dir.getName());
    if (files != null && files.length > 0) {
    
    
        for(File file : files){
    
    
            if(file.isDirectory()){
    
    
                listDir(file);
            }else {
    
    
                System.out.println(file.getName());
            }
        }
    }
}

递归删除文件夹

public static void deleteDir(File dir){
    
    
    File[] files = dir.listFiles();
    if(files!=null && 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. 存储属性名和属性值
    2. 属性名和属性值都是字符串类型
    3. 没有泛型
    4. 和流有关
//Properties集合的使用
public static void main(String[] args) throws Exception{
    
    
    //1. 创建集合
    Properties properties = new Properties();
    //2. 添加数据
    properties.setProperty("username","zhangsan");
    properties.setProperty("age","20");
    System.out.println(properties.toString());
    //3. 遍历
    //3.1 keyset
    //3.2 entrySet
    //3.3 stringPropertyNames()
    Set<String> pronames = properties.stringPropertyNames();
    for(String pro : pronames){
    
    
        System.out.println(pro + "-" + properties.get(pro));
    }

    //和流有关的方法
    //4.1 list方法
    PrintWriter pw =new PrintWriter("路径/print.txt");
    properties.list(pw);
    pw.close();
    //4.2 store方法 保存
    FileOutputStream fos = new FileOutputStream("路径/print.properties");
    properties.store(fos,"注释");
    fos.close();
    //4.3 load方法 加载
    Properties properties2 = new Properties();
    FileInputStream fis = new FileInputStream("路径/print.properties");
    properties2.load(fis);
    fis.close();
    System.out.println(properties2.toString());
}

猜你喜欢

转载自blog.csdn.net/weixin_42823298/article/details/128646455