【Java高级编程】IO流学习笔记

IO流

I(input)O(output)。

流的分类:

  • 按照读写方向,分为输入流和输出流。(在程序角度分析)
  • 按照读写内容单位而言,分为字节流和字符流
  • 按照流的功能不同,分为节点流和处理流
    • 字节流:直接连接在文件上
    • 处理流:嵌套在其它流上

流的家族体系

- 输入 输出
字节流 InputStream OutputStream
字符流 Reader Writer

上面四个都是抽象类
对应文件流:

  • 文件字节输入流 FileInputStream
  • 文本字节输出流FileOutputStream
  • 字符输入流:FileReader
  • 字符输入流:FileWriter

File类

表示操作系统中的文件或者文件夹。

  • 文件路径
    • 绝对路径
    • 相对路径

文件/文件夹基础操作

package eg01_file;

import java.io.File;
import java.io.IOException;

public class Test1 {
    public static void main(String[] args) {
        boolean result = false;
        File file = new File("test01.txt"); // 该文件可有可无
        try {
            result = file.createNewFile();//create a file. create file not folder
            System.out.println("文件创建"+ (result ?"成功":"失败"));
            System.out.println(file.getParent());// 拿到上一级文件夹路径
            System.out.println(file.getParentFile());//拿到上一级文件夹的文件对象
            file.mkdir();//创建单个文件夹。
            file.mkdirs();//支持同时创建多级目录
            result  = file.renameTo(new File("test01_change.txt"));
            System.out.println("文件修改名称"+ (result ?"成功":"失败"));

            //查看相关
            System.out.println(file.exists());//文件是否存在
            System.out.println(file.isAbsolute());//是否是绝对路径
            System.out.println(file.isDirectory());//是否是文件夹
            System.out.println(file.isFile());//是否是文件夹
            System.out.println(file.length());//查看文件大小
        } catch (IOException e) {
            e.printStackTrace();//查看文件是否存在
        }
    }
}

创建文件的完整步骤

package eg01_file;

import java.io.File;

public class Test2 {
    public static void main(String[] args) {
    try{
        File file = new File("abc/test2.txt");
        //判断上层文件夹是否存在
        File parentFile = file.getParentFile();
        if(!parentFile.exists()){
            //上层文件夹不存在,先创建
            parentFile.mkdirs();
        }
        //创建文件
        file.createNewFile();
    }catch (Exception e){
        e.printStackTrace();
    }
    }
}

IO流 - 节点流

读入文件一个字节(一个字节)

不能读取中文。中文是2个字节一个字

package eg02_io;

import java.io.FileInputStream;
import java.io.InputStream;


public class TestFileInputStream {
  public static void main(String[] args) {
    //创建流
    try {
      InputStream fis = new FileInputStream("test01.txt");
      //----------------------------------------------
      int result = fis.read();//读出来的是字符ASCII码
      System.out.println((char) result);//强制转换
      //---------------------------------------------- 
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

[FileInputStream]字节数组的方式读取(读取全部内容)

package eg02_io;

import java.io.FileInputStream;
import java.io.InputStream;


public class TestFileInputStream {
  public static void main(String[] args) {
    //创建流
    try {
      InputStream fis = new FileInputStream("test01.txt");
      byte[] bs = new byte[1024];//一次读kb
      int len = fis.read(bs);//读出来的是字节数组。返回值为读取的字节数量。
      System.out.println(new String(bs, 0, len));//字节数组转为字符
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

[FileInputStream]读取文件最重要的一套写法

package eg02_io;

import java.io.FileInputStream;
import java.io.InputStream;


public class TestFileInputStream {
  public static void main(String[] args) {
    //创建流
    try {
      InputStream fis = new FileInputStream("test01.txt");
      byte[] bs = new byte[1024];//一次读kb
      int len = 0;
      while ((len = fis.read(bs)) != -1) {// 不等于-1表示没读完,便继续读取。
        //该写法仅限于IO流使用,其他地方不要用。
        String s = new String(bs, 0, len);
        System.out.println(s);
      }
      //关流
      fis.close();

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

[FileoutputStream]向文件写入内容

package eg02_io;

import java.io.File;
import java.io.FileOutputStream;

public class TestFileOutputStream {
  public static void main(String[] args) {
    try {
      FileOutputStream fos = new FileOutputStream(new File("test01.txt"), true);//true追加。则不会清空原有数据
      fos.write("牛啊牛啊,醉酒的向日狼".getBytes());
      fos.flush();
      fos.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

[FileReader]读入文件一个字符(两个字节)

package eg02_io;

import java.io.File;
import java.io.FileReader;

public class TestFileReader {
  public static void main(String[] args) {
    try {
      FileReader fr = new FileReader(new File("test01.txt"));
      int i = fr.read();//以字符为单位。
      System.out.println((char) i);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

[FileReader]读入文件所有字符

package eg02_io;

import java.io.File;
import java.io.FileReader;

public class TestFileReader {
  public static void main(String[] args) {
    try {
      FileReader fr = new FileReader(new File("test01.txt"));
      char[] cs = new char[1024];
      int len = fr.read(cs);
      System.out.println(new String(cs, 0, len));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

对于存在大量内容需要读取时的写法

package eg02_io;

import java.io.File;
import java.io.FileReader;

public class TestFileReader {
  public static void main(String[] args) {
    try {
      FileReader fr = new FileReader(new File("test01.txt"));
      char[] cs = new char[1024];
      int len = 0;
      while ((len = fr.read(cs)) != -1) {
        System.out.println(new String(cs, 0, len));
      }
      fr.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

[FileWriter]向文件写入内容

package eg02_io;

import java.io.File;
import java.io.FileWriter;

public class TestFileWriter {
  public static void main(String[] args) {
    try {
      FileWriter fw = new FileWriter(new File("test01.txt"), true);//追写则true
      fw.write("刑啊,太刑了。");
      fw.flush();
      fw.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

如何选择流?

字节流:常用于读取非文本文件

字符流:常用于读取文件中的文字信息

IO流练习:复制图片操作

选择的流:字节流

package eg03_copypic;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class test3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream(new File("1.jpg"));
        FileOutputStream fos = new FileOutputStream(new File("2.jpg"),true);
        byte[] bs = new byte[1024];
        int len = 0;
        while ((len = fis.read(bs))!=-1){
            fos.write(bs,0,len);
        }
        fis.close();
        fos.flush();
        fos.close();
    }
}

如果不是复制,而是剪切

package eg03_copypic;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class test3 {
    public static void main(String[] args) throws IOException {
        File file = new File("2.jpg");
        FileInputStream fis = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(new File("3.jpg"),true);
        byte[] bs = new byte[1024];
        int len = 0;
        while ((len = fis.read(bs))!=-1){
            fos.write(bs,0,len);
        }
        fis.close();
        fos.flush();
        fos.close();
        file.delete();
    }
}

IO流 - 处理流

缓冲流

缓冲流:带有缓冲区的数据流

重点是BufferedReader ,这是读取文本文件最好的方式

  • BufferedInputStream
  • BufferedOutputStream
  • BufferedReader
  • BufferedWirter
package eg04.buffer;

import java.io.*;

public class test04 {
    public static void main(String[] args) throws IOException {

       // BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("test01.txt"))); //一般不用
        BufferedReader br = new BufferedReader(new FileReader(new File("test01.txt")));
//        System.out.println(br.readLine()); //读取文本文件最好用的方法。
//        System.out.println(br.readLine());
        String str = "";
        while ((str= br.readLine())!=null){
            //读取内容
            System.out.println(str);
        }
        br.close();
    }
}

转换流

字节流 ==> 字符流 :

  • [输入] InputStreamReader
  • [输出] OutputStreamWriter
package eg05_convert;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class test_out {
    public static void main(String[] args) throws IOException {
//        System.out.println();
        Writer writer = new OutputStreamWriter(System.out);
        writer.write("abc路人甲");
        writer.flush();
        //writer.close();//有时候流不可以关,如果这里关了,后面的 System.out.println(); 也不会输出。
        System.out.println("关闭了流");
    }
}

对象流

  • ObjectInputStream
  • ObjectOutputStream

[对象] Person.java

package eg06_obj;

public class Person {
    private int id;
    private String name;
    private int age;

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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;
    }
}

[测试] test06.java

package eg06_obj;

import java.io.*;

public class test06 {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("person.data")));
        Person p = new Person(1,"萌狼蓝天",18);
        oos.writeObject(p);
        oos.flush();
        oos.close();
    }
}

[运行结果]报错

img.png

序列化:把一个对象转化为字节的过程
反序列化:把字节转化成对象

解决方案:在Java中只需要给类添加一个实现,Serialable。这样这个类就可以被序列化了。过程是全自动的。(实质:让数据可以进行序列化)

更改 Person.java

package eg06_obj;

import java.io.Serializable;

public class Person implements Serializable {
    private int id;
    private String name;
    private int age;

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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;
    }
}

此时运行,便不会报错。

那么如何读取呢?(反序列化)

package eg06_obj;

import java.io.*;

public class Test07 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("person.data")));
        Object obj =  ois.readObject();
        Person p = (Person) obj;
        System.out.println(p.getName());
    }
}

文件修改操作

思路:偷梁换柱。逐行读取文件内容,将内容进行替换,将替换结果记录在一个新文件中,直到数据写入完毕,把源文件删除。

把新文件的名字改成源文件的名字

代码如下

package eg07_update;

import java.io.*;
import java.nio.Buffer;

public class test7 {
    public static void main(String[] args) throws Exception {
        File res  = new File("test.txt");
        //没有test.txt需要先手动创建,内容如下
        /**
         * 记录生活的博客:萌狼蓝天の小世界 - 萌狼蓝天 (mllt.cc)
         *
         * 记录学习笔记的博客:萌狼蓝天 - 博客园 (cnblogs.com)
         *
         * 分享信息技术相关内容的哔哩哔哩账号:萌狼蓝天的个人空间_哔哩哔哩_bilibili
         *
         * 分享个人生活的哔哩哔哩账号:醉酒的向日狼的个人空间_哔哩哔哩_bilibili
         *
         * 这四个网站是我主要活跃的网站
         *
         * 其中,mllt.cc这个网站是搭建在我自己服务器的,也许我会因为续费不起服务器而在2023年的时候关闭这个网站。
         *
         * 如果你想获取我的学习笔记,应该去看我的博客园
         *
         * 如果你想观看我录制的计算机相关知识视频,应该去看萌狼蓝天的个人空间_哔哩哔哩_bilibili
         */
        File new_res  = new File("副本_test.txt");

        BufferedReader br = new BufferedReader(new FileReader(res));

        BufferedWriter bw = new BufferedWriter(new FileWriter(new_res));

        String line = "";

        while((line = br.readLine())!=null){
            line = line.replace("萌狼蓝天","易水千");
            bw.write(line);
            bw.newLine();//另起一行(换行)
        }
        br.close();
        bw.flush();
        bw.close();
        //删除源文件
        res.delete();
        //重命名新文件
        new_res.renameTo(res);

    }
}

[运行结果]

img.png

posted @ 2022-08-25 19:41  萌狼蓝天  阅读(40)  评论(0编辑  收藏  举报