Java-IO

IO 框架

1、流的概念

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

流的概念

小贴士:

​ 水借助管道传输; 数据借助流传输

2、流的分类

2.1 按方向【重点】

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

2.2 按单位

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

2.3 按功能

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

3、字节流

3.1 字节流的父类(抽象类)

// InputStream 字节输入流
public int read(){} //从输入流中读取一个字节返回int型变量,若到达文件末尾,则返回-1
public int read(byte[] b){} //从输入流中读取b.length个字节到字节数组中,返回读入缓冲区的总
public int read(byte[] b, int off, int len){} //从输入流中读取最多len个字节到字节数组中												// (从数组的off位置开始存储字节)

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

3.2 文件字节流

3.2.1 文件输入流
public static void main(String[] args) throws IOException {
    // 1 创建FileInputStream,并指定文件路径
    File file;
    FileInputStream fis = new FileInputStream("F:\\IDEA_Workspace\\Java IO框架\\字节流\\aaa.txt");
    // 2 读取文件
    // fis.read();
    // 2.1 单个字节读取
    int data =0;
    while((data=fis.read())!=-1){
        System.out.println((char) data);
    }      
    // 2.2 一次读取多个字节
    byte[] buf = new byte[3]; // 大小为3的缓存区
    
    
//        int count = fis.read(buf); // 一次读3个
//        System.out.println(new String(buf));
//        System.out.println(count);
//        int count2 = fis.read(buf); // 再读3个
//        System.out.println(new String(buf));
//        System.out.println(count2);
   
    //上述优化后
    int count = 0; 
    while((count = fis.read(buf)) != -1){ // -1 表示读完
         System.out.println(new String(buf, 0, count));
    }
    // 3 关闭
    fis.close();
}
3.2.2 文件输出流
public static void main(String[] args) throws IOException {
    // 1 创建文件字节输出流
    FileOutputStream fos = new FileOutputStream("F:\\IDEA_Workspace\\Java IO框架\\字节流\\bbb.txt", true);// true表示不覆盖 接着写
    // 2 写入文件
    fos.write(97);
    fos.write('a');
    String string = "hello world";
    fos.write(string.getBytes());
    // 3 关闭
    fos.close();
}
3.2.3 图片复制案例
public static void main(String[] args) throws IOException {
    // 1 创建流
    // 1.1 文件字节输入流
    FileInputStream fis = new FileInputStream("001.jpg");
    // 1.2 文件字节输出流
    FileOutputStream fos = new FileOutputStream("002.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();
}

3.3 字节缓冲流

缓冲流:BufferedInputStream/ BufferedOutputStream

  • 提高IO效率,减少访问磁盘次数
  • 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close
3.3.1 使用字节缓冲流 读取 文件
// 使用字节缓冲流 读取 文件
public static void main(String[] args) throws IOException {
    // 1 创建BufferedInputStream
    FileInputStream fis = new FileInputStream("F:\\IDEA_Workspace\\Java IO框架\\字节流\\aaa.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();
}
3.3.2 使用字节缓冲流 写入 文件
// 使用字节缓冲流 写入 文件
public static void main(String[] args) throws IOException {
    // 1 创建BufferedInputStream
    FileOutputStream fos = new FileOutputStream("F:\\IDEA_Workspace\\Java IO框架\\字节流\\buffer.txt");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    // 2 写入文件
    for(int i = 0; i < 10; i ++){
        bos.write("hello".getBytes());// 写入8k缓冲区
        bos.flush(); // 刷新到硬盘(虽然会造成效率不高但会防止数据丢失)
    }
    // 3 关闭
    bos.close();
}

4、对象流

ObjectOutputStream / ObjectInputStream

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

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

5、序列化与反序列化

将对象通过流写入到文件(序列化),或将对象通过流读取到内存(反序列化),必须实现Serializable接口

5.1 序列化

// 学生类
public class Student implements Serializable {
    private static final long serialVersionUID=100L; // 序列化号
    private String name;
    private int age;
    public Student() {
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    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;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
// 使用ObjectOutputStream实现对象的序列化
// 要求:序列化类必须要实现Serializable接口
public static void main(String[] args) throws IOException {
    // 1. 创建对象流
    FileOutputStream fos = new     FileOutputStream("F:\\IDEA_Workspace\\Java IO框架\\字节流\\st.bin");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    // 2. 序列化(写入操作)
    Student zhangsan = new Student("zs", 20);
    oos.writeObject(zhangsan);
    // 3. 关闭
    oos.close();
    System.out.println("序列化完毕");
}

5.2 反序列化

// 使用MyObjectInputStream实现反序列化(读取重构成对象)
public static void main(String[] args) throws IOException, ClassNotFoundException {
    // 1. 创建对象流
    FileInputStream fis = new FileInputStream("F:\\IDEA_Workspace\\Java IO框架\\字节流\\st.bin");
    ObjectInputStream ois = new ObjectInputStream(fis);
    // 2. 读取文件(反序列化)
    Student s = (Student)ois.readObject();
    // 3. 关闭
    ois.close();
    System.out.println("执行完毕");
    System.out.println(s.toString());
}

5.3 注意事项

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

6、字符编码

使用 UTF-8 即可

小贴士:

​ 当编码方式和解码方式不一致时,会出现乱码

7、字符流

7.1 字符流的父类(抽象类)

// 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){}

7.2 文件字符流

7.2.1 字符输入流
// 使用FileReader读取文件 
public static void main(String[] args) throws IOException {
        // 1. 创建FileReader 文件字符输入流
        FileReader fr = new FileReader("F:\\IDEA_Workspace\\Java IO框架\\字符流\\hello.txt");
        // 2. 读取
        // 2.1 单个字符读取
//        int data = 0;
//        while((data = fr.read()) != -1){
//            System.out.println((char)data);// 读取一个字符
//        }
        // 字符缓冲区读取
        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();
    }
7.2.2 字符写入流
// 使用FileWriter写入文件
public static void main(String[] args) throws IOException {
    // 1. 创建FileWriter对象
    FileWriter fw = new FileWriter("F:\\IDEA_Workspace\\Java IO框架\\字符流\\write.txt");
    // 2. 写入
    for(int i = 0; i < 10; i ++){
        fw.write("写入的内容\r\n"); //  换行\r\n
        fw.flush();
    }
    // 3. 关闭
    fw.close();
    System.out.println("执行完毕");
}
7.2.3 文本文件复制案例

不能复制图片或二进制文件,使用字节流可以复制任意文件

public static void main(String[] args) throws IOException {
    // 1. 创建
    FileReader fr = new FileReader("F:\\IDEA_Workspace\\Java IO框架\\字符流\\write.txt");
    FileWriter fw = new FileWriter("F:\\IDEA_Workspace\\Java IO框架\\字符流\\write2.txt");
    // 2. 读写
    int data = 0;
    while((data = fr.read()) != -1){
        fw.write(data);
        fw.flush();
    }
    // 3. 关闭
    fw.close();
    fr.close();

7.3 字符缓冲流

BufferedReader / BufferedWriter

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

7.3.1 使用字符缓冲流读取文件
// 使用字符缓冲流读取文件
public static void main(String[] args) throws IOException {
    // 创建缓冲流
    FileReader fr = new FileReader("F:\\IDEA_Workspace\\Java IO框架\\字符流\\write.txt");
    BufferedReader br = new BufferedReader(fr);
    // 读取
    // 1. 第一种方式
//    char[] buf = new char[1024];
//    int count = 0;
//    while((count = br.read(buf)) != -1){
//       System.out.println(new String(buf, 0, count));
//    }
    // 2. 第二种方式 一行一行读取
    String line = null;
    while((line = br.readLine()) != null){
        System.out.println(line);
    }

    // 关闭
    br.close();
}
7.3.2 使用字符缓冲流写入文件
//  使用字符缓冲流写入文件
public static void main(String[] args) throws IOException {
    // 1. 创建BufferedWriter对象
    FileWriter fw = new FileWriter("F:\\IDEA_Workspace\\Java IO框架\\字符流\\buffer.txt");
    BufferedWriter bw = new BufferedWriter(fw);
    // 2. 写入
    for(int i = 0; i < 10; i++){
        bw.write("写入的内容");
        bw.newLine(); // 写入一个换行符 windows \r\n  linux \n
        bw.flush();
    }
    // 3. 关闭
    bw.close(); // 此时会自动关闭fw
}

8、打印流(PrintWriter)

封装了print() / println() 方法 支持写入后换行

支持数据原样打印

public static void main(String[] args) throws FileNotFoundException {
    // 1 创建打印流
    PrintWriter pw = new PrintWriter("F:\\IDEA_Workspace\\Java IO框架\\打印流\\print.txt");
    // 2 打印
    pw.println(12);
    pw.println(true);
    pw.println(3.14);
    pw.println('a');
    // 3 关闭
    pw.close();
}

9、转换流

  • 桥转换流 InputStreamReader / OutputStreamWriter
    • 可将字节流转换为字符流
    • 可设置字符的编码方式

9.1 InputStreamReader 读取文件

// 使用InputStreamReader读取文件,指定使用的编码
public static void main(String[] args) throws IOException {
    // 1 创建InputStreamReader对象
    FileInputStream fis = new FileInputStream("F:\\IDEA_Workspace\\Java IO框架\\字符流\\write.txt");
    InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
    // 2 读取文件
    int data = 0;
    while((data = isr.read()) != -1){
        System.out.print((char)data);
    }
    // 3 关闭
    isr.close();
}

9.2 OutputStreamWriter 写入文件

// 使用OutputStreamWriter写入文件,使用指定的编码格式
public static void main(String[] args) throws IOException {
    // 1 创建OutputStreamReader对象
    FileOutputStream fos = new FileOutputStream("F:\\IDEA_Workspace\\Java IO框架\\转换流\\print.txt");
    OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
    // 2 写入
    for(int i = 0; i < 10; i ++){
        osw.write("写入内容\r\n");
        osw.flush();
    }
    // 3 关闭
    osw.close();
}

10、File 类

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

  • 方法:

        createNewFile() 	 // 创建一个新文件
        mkdir()				// 创建一个新目录
        delete()			// 删除文件或空目录
        exists()			// 判断
        getAbsolutePath() 	 // 获取文件的绝对路径  
        getName()			// 获取文件名
        getParent()			// 获取文件/目录所在的目录
    	isDirectory()		// 是否是目录
        isFile()			//是否是文件
        lenth()				// 获得文件的长度
        listFiles()			// 列出目录中的所有内容
        renameTo()			// 修改文件名为
    

10.1 文件的操作

// 使用方法    
public static void main(String[] args) throws Exception {
    separator();
    fileOpen();
}
// (1). 分隔符
public static void separator(){
    System.out.println("路径分隔符:" + File.pathSeparator);
    System.out.println("名称分隔符:" + File.separator);
}
// (2). 文件操作
public static void fileOpen() throws Exception {
    // 1. 创建文件
    File file = new File("F:\\IDEA_Workspace\\Java IO框架\\文件类\\file.txt");
    if (!file.exists()) {   // 是否存在
        boolean b = file.createNewFile();
        System.out.println("创建结果:"+b);
    }
    // 2. 删除文件
    // 2.1 直接删除
    file.delete(); // 成功true
    // 2.2 使用jvm退出时删除
    file.deleteOnExit();
    // 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). 文件夹操作
    private static void directoryOpe() {
        // 1. 创建文件夹
        File dir = new File("F:\\IDEA_Workspace\\Java IO框架\\文件类\\aaa\\bbb\\ccc");
        System.out.println(dir.toString());
        if(!dir.exists()){
            //dir.mkdir(); // 只能创建单级目录
            dir.mkdirs(); // 创建多级目录
        }

        // 2. 删除文件夹
        // 2.1 直接删除
        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.isFile());
        System.out.println("是否隐藏" + dir.isHidden());
        
        // 5. 遍历文件夹
        File dir2 = new File("D:\\图片");
        String[] files = dir2.list();
        for(String string : files){
            System.out.println(string);
        }
    }

10.2 FileFilter 接口

  • boolean accept(File pathname): 测试pathname是否应该包含在当前的File目录中,如果符合返回true
  • 当调用File类中的listFiles()方法时,支持传入FileFilter 接口接口实现类,对获取文件进行过滤,只有满足条件的文件才可出现在listFiles()的返回值中
  // FileFilter接口的使用 
  	File dir2 = new File("D:\\图片");
    File[] files2 = dir2.listFiles(new FileFilter(){  
      @Override
      public boolean accept(File pathname){
        if(pathname.getName().endsWith(".jpg")){
          return true;
        }
        return false;
      }
    });
    for(File file : files2){
      sout(file.getName());
    }  
  }

10.3 递归遍历文件夹

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

10.4 递归删除文件夹

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());
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江七7

感谢大佬的赏赐

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值