IO流

I(Input 输入)/ O(Output 输出)流,是Java中用来传输数据的方式。

一、划分

按照流向:

  • 输入流:从文件 读数据 到内存
  • 输出流:从内存 写数据 到文件

按照操作:

  • 字符流:以字符为单位操作数据
  • Reader:字符输入流的顶层抽象类
  • FileReader:普通的字符输入流
  • BufferedReader:高效的字符输入流(字符缓冲输入流)
  • Writer:字符输出流的顶层抽象类
  • FileWriter:普通的字符输出流
  • BufferedWriter:高效的字符输出流(字符缓冲输出流)
  • 字节流:以字节为单位操作数据
  • InputStream:字节输入流的顶层抽象类
  • FileInputStream:普通的字节输入流
  • BufferedInputStream:高效的字节输入流(字节缓冲输入流)
  • OutputStream:字节输出流的顶层抽象类
  • FileOutputStream:普通的字节输出流
  • BufferedOutputStream:高效的字节输出流(字节缓冲输出流)

二、File类

文件,文件夹,一个File对象代表磁盘上的某个文件或文件夹

2.1 构造方法

  • File(String pathname)
  • File(String parent, String child)
  • File(File parent, String child)
File file1 = new File("D:/abc/1.txt");
System.out.println("file1: " + file1);

File file2 = new File("D:/abc/", "1.txt");
System.out.println("file2: " + file2);

File file3 = new File("D:/abc/");
File file4 = new File(file3, "1.txt");
System.out.println("file4: " + file4);

2.2 成员方法

  • 创建功能:如果不存在就创建,返回true;否则就不创建,返回false
  • createNewFile():创建文件
  • mkdir():创建单级目录
  • mkdirs():创建目录
File file5 = new File("F:/abc/2.txt");
boolean flag1 = file5.createNewFile();
System.out.println("flag1: " + flag1);

File file6 = new File("F:/a");
boolean flag2 = file6.mkdir();
System.out.println("flag2: " + flag2);

File file7 = new File("F:/b/c");
boolean flag3 = file7.mkdirs(); // 也可以创建单级目录
System.out.println("flag3: " + flag3);
  • 判断功能:
  • isDirectory():判断File对象是否为目录
  • isFile():判断File对象是否为文件
  • exists():判断File对象是否存在
File file8 = new File("F:/a/b");
System.out.println("判断file8是否为文件夹:" + file8.isDirectory());
System.out.println("判断file8是否为文件:" + file8.isFile());
System.out.println("判断file8是否存在:" + file8.exists());
  • 获取功能:
  • getAbsolutePath():获取绝对路径
    绝对路径:以盘符开头的路径,例如D:/1.txt
  • getPath():获取文件的相对路径
    相对路径:一般是相对于当前项目的路径而言,例如1.txt
  • getName():获取文件名
File file1 = new File("lib/3.txt");
file1.createNewFile();

String path1 = file1.getAbsolutePath();
System.out.println("绝对路径:" + path1);

String path2 = file1.getPath();
System.out.println("相对路径:" + path2);

String name = file1.getName();
System.out.println("文件名称:" + name);
  • list():获取指定目录下所有文件(夹)的名称数组
  • listFile():获取指定目录下所有文件(夹)的File数组
File file2 = new File("lib");

String[] names = file2.list();
System.out.println("lib目录下的文件(夹)名称如下:");
for (String s : names) {
	System.out.println(s);
}

File[] files = file2.listFiles();
System.out.println("lib目录下的文件(夹)数组如下:");
for (File file : files) {
	System.out.println(file);
}

三、字符流

字符流只能拷贝纯文本文件!

3.1 字符输入流:Reader

  1. 创建字符输入流对象FileReader
  2. 读取数据
  3. 释放资源

例子1:一次读取一个字符

public class ReaderDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字符输入流对象
        Reader reader = new FileReader("lib/3.txt");

        // 2.读取数据
        /*
            2.1 reader.read(),到文件中读取一个字符
            2.2 ch = reader.read(),将读取到的字符赋值给变量ch
            2.3 (ch = reader.read()) != -1,用读取到的字符(变量)和 -1 进行比较,若文件已经读完,会返回 -1
         */
        int ch;
        while ((ch = reader.read()) != -1) {
            System.out.println(ch);
        }

        // 3.释放资源
        reader.close();
    }
}

例子2:一次读取一个字符数组

public class ReaderDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字符输入流对象
        Reader reader = new FileReader("lib/3.txt");

        // 2.读取数据
        /*
            2.1 reader.read(chs),到文件中读取若干字符到字符数组 chs中
            2.2 len = reader.read(chs),将读取到的有效字符数量赋值给变量 len
            2.3 (len = reader.read(chs)) != -1,用读取到的字符数量(变量)和 -1 进行比较,若文件已经读完,会返回 -1
         */
        char[] chs = new char[3];
        int len;
        while ((len = reader.read(chs)) != -1) {
            String s = new String(chs,0,len);
            System.out.println(s);
        }

        // 3.释放资源
        reader.close();
    }
}

3.2 字符输出流:Writer

  1. 创建字符输出流对象FileWriter
  2. 写入数据
void write(int ch); // 一次写一个字符
void write(char[] chs, int index, int len); //一次写一个字符数组
void write(String str); //一次写一个字符串
  1. 释放资源
public class WriterDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字符输出流对象
        Writer writer = new FileWriter("lib/3.txt");

        // 2.写入数据
        // 2.1一次写入一个字符
        writer.write("好");

        // 2.2一次写入一个字符数组,起始 和 长度
        char[] chars = {'华','南','农','业','大','学'};
        writer.write(chars,1,2);

        // 2.3一次写入一个字符串
        writer.write("信息与计算科学");
        
        // 3.释放资源
        writer.close();
    }
}

3.3 字符流拷贝:Reader + Writer

  1. 创建字符输入流对象,关联数据源文件
  2. 创建字符输出流对象,关联目的地文件
  3. 定义变量,用于记录读取到的内容
  4. 循环读取,将读取到的内容赋值给变量
  5. 将读取到的数据写入到 目的地文件中
  6. 释放资源

例子1:一次拷贝一个字符

public class CopyDemo {
    public static void main(String[] args) throws IOException {
        // 1. 创建字符输入流对象,关联数据源文件
        FileReader fr = new FileReader("lib/1.txt");
        // 2. 创建字符输出流对象,关联目的地文件
        FileWriter fw = new FileWriter("lib/3.txt");
        // 3. 定义变量,用于记录读取到的内容
        int ch;
        // 4. 循环读取,将读取到的内容赋值给变量
        while ((ch = fr.read()) != -1) {
            // 5. 将读取到的数据写入到 目的地文件中
            fw.write(ch);
        }
        // 6. 释放资源
        fr.close();
        fw.close();
    }
}

例子2:一次拷贝一个字符数组

public class CopyDemo {
    public static void main(String[] args) throws IOException {
        // 1. 创建字符输入流对象,关联数据源文件
        FileReader fr = new FileReader("lib/1.txt");
        // 2. 创建字符输出流对象,关联目的地文件
        FileWriter fw = new FileWriter("lib/3.txt");
        // 3. 定义变量,用于记录读取到的内容
        char[] chs = new char[1024];
        int len;
        // 4. 循环读取,将读取到的内容赋值给变量,将读取到的有效字符数量赋值给变量 len
        while ((len = fr.read(chs)) != -1) {
            // 5. 将读取到的数据写入到 目的地文件中
            fw.write(chs,0,len);
        }
        // 6. 释放资源
        fr.close();
        fw.close();
    }
}

3.4 字符缓冲流拷贝

  1. 创建字符缓冲输入流对象,关联数据源文件
new BufferedReader(Reader reader);
  1. 创建字符缓冲输出流对象,关联目的地文件
new BufferedWriter(Writer writer);
  1. 字符缓冲流自带缓冲区,大小为8192个字符,即16KB
  2. 定义变量,用于记录读取到的内容
  3. 循环读取,将读取到的内容赋值给变量
  4. 将读取到的数据写入到 目的地文件中
  5. 释放资源
public class CopyDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字符缓冲输入流对象,关联数据源文件
        FileReader fr = new FileReader("lib/1.txt");
        BufferedReader br = new BufferedReader(fr);

        // 2.创建字符缓冲输出流对象,关联目的地文件
        FileWriter fw = new FileWriter("lib/3.txt");
        BufferedWriter bw = new BufferedWriter(fw);

        // 3.定义变量,用于记录读取到的内容
        int len;

        // 4.循环读取,将读取到的内容赋值给变量
        while ((len = br.read()) != -1) {
            // 5.将读取到的数据写入到 目的地文件中
            bw.write(len);
        }

        // 6.释放资源
        bw.close();
        fw.close();
        br.close();
        fr.close();
    }
}

一次读取写一行:

一次读取一行数据并返回读取到的内容,读不到就返回null

public String readLine(){};

根据当前操作系统给出对应的换行符

public void newLine(){};

操作系统

换行符

windows

\r\n

mac

\r

unix

\n

public class CopyDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字符缓冲输入流对象,关联数据源文件
        BufferedReader br = new BufferedReader(new FileReader("lib/1.txt"));
        // 2.创建字符缓冲输出流对象,关联目的地文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("lib/3.txt"));

        // 3.定义变量,用于记录读取到的内容
        String str;
        // 4.循环读取,将读取到的内容赋值给变量
        while ((str = br.readLine()) != null) {
            // 5.将读取到的数据写入到 目的地文件中
            bw.write(str);
            // 注意换行
            bw.newLine();
        }

        // 6.释放资源
        bw.close();
        br.close();
    }
}

四、字节流

拷贝纯文本文件使用字符流,拷贝其他==(图片、音频、视频等)==使用字节流

4.1 字节流拷贝

InputStream + OutputStream

  1. 创建字节输入流对象FileInputStream,关联数据源文件
  2. 创建字节输出流对象FileOutputStream,关联目的地文件
  3. 定义变量,用于记录读取到的内容
  4. 循环读取,将读取到的内容赋值给变量
  5. 将读取到的数据写入到 目的地文件中
  6. 释放资源

例子1:一次拷贝一个字节

public class CopyDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字节输入流对象,关联数据源文件
        FileInputStream fis = new FileInputStream("lib/a.jpg");
        // 2.创建字节输出流对象,关联目的地文件
        FileOutputStream fos = new FileOutputStream("lib/b.jpg");

        // 3.定义变量,用于记录读取到的内容
        int by;
        // 4.循环读取,将读取到的内容赋值给变量
        while ((by = fis.read()) != -1) {
            // 5.将读取到的数据写入到 目的地文件中
            fos.write(by);
        }

        // 6.释放资源
        fos.close();
        fis.close();
    }
}

例子2:一次拷贝一个字节数组

public class CopyDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字节输入流对象,关联数据源文件
        FileInputStream fis = new FileInputStream("lib/b.jpg");
        // 2.创建字节输出流对象,关联目的地文件
        FileOutputStream fos = new FileOutputStream("lib/c.jpg");

        // 3.定义变量,用于记录读取到的内容
        byte[] bys = new byte[2048];
        int len;
        // 4.循环读取,将读取到的内容赋值给变量,将读取到的有效字符数量赋值给变量 len
        while ((len = fis.read(bys)) != -1) {
            // 5.将读取到的数据写入到 目的地文件中
            fos.write(bys,0,len);
        }

        // 6.释放资源
        fos.close();
        fis.close();
    }
}

4.2 字节缓冲流拷贝

  1. 创建字节缓冲输入流对象,关联数据源文件
new BufferedInputStream(InputStream is);
  1. 创建字节缓冲输出流对象,关联目的地文件
new BufferedOutputStream(OutputStream os);
  1. 字节缓冲流自带缓冲区,大小为8192个字节,即8KB
  2. 定义变量,用于记录读取到的内容
  3. 循环读取,将读取到的内容赋值给变量
  4. 将读取到的数据写入到 目的地文件中
  5. 释放资源
public class CopyDemo {
    public static void main(String[] args) throws IOException {
        // 1.创建字节缓冲输入流对象,关联数据源文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("lib/a.jpg"));
        // 2.创建字节缓冲输出流对象,关联目的地文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/d.jpg"));

        // 3.定义变量,用于记录读取到的内容
        int len;
        // 4.循环读取,将读取到的内容赋值给变量
        while ((len = bis.read()) != -1) {
            // 5.将读取到的数据写入到 目的地文件中
            bos.write(len);
        }

        // 6.释放资源
        bos.close();
        bis.close();
    }
}