IO流

  • IO流
  • java.io下需要掌握的16个流
  • 文件专属
  • java.io.FileInputStream(重点)
  • java.io.FileOutputStream(重点)
  • java.io.FileReader
  • java.io.FileInWhiter
  • 转换流
  • java.io.InputStreamReader
  • java.io.OutputStreamReader
  • 缓冲流专属
  • java.io.BufferedReader
  • java.io.BufferedWriter
  • java.io.BufferedInputStream
  • java.io.BufferedOutputStream
  • 数据流专属
  • java.io.DataInputStream
  • java.io.DataOutputStream
  • 标准输出流
  • java.io.PrintWriter
  • java.io.PrintStream(重点)
  • 对象专属流:
  • java.io.ObjectInputStream(重点)
  • java.io.ObjectOutputStream(重点)
  • java.io.File类


IO流

java中所有的流都是在:java.io.*;下。

java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流

java.io.Reader 字符输入流
java.io.Writer 字符输出流

所有的流都实现了:java.io.Closeable接口,都是可关闭的,都有close()方法。
流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。

所有的输出流都实现了:java.io.Flushable接口,都是可刷新的,都有flush()方法。
养成一个好习惯,输出流在最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。
注意:如果没有flush()可能会导致丢失数据。

java.io下需要掌握的16个流

文件专属:
java.io.FileInputStream 文件字节输入流
java.io.FileOutputStream 文件字节输出流
java.io.FileReader 文件字符输入流
java.io.FileWhiter 文件字符输出流
 转换流:
java.io.InputStreamReader 将输入字节流转换成输入字符流
java.io.OutputStreamReader 将输出字节流转换成输出字符流
 缓冲流专属:
java.io.BufferedReader 带有缓冲区的字符输入流
java.io.BufferedWriter 带有缓冲区的字符输出流
java.io.BufferedInputStream 带有缓冲区的字节输入流
java.io.BufferedOutputStream 带有缓冲区的字节输出流
 数据流专属:
java.io.DataInputStream 数据字节输入流
java.io.DataOutputStream 数据字节输出流
 标准输出流:
java.io.PrintWriter 标准的字节输入流
java.io.PrintStream 标准的字节输出流
 对象专属流:


java.io.ObjectInputStreamjava.io.ObjectOutputStream

文件专属

java.io.FileInputStream(重点)

1.文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。
2.字节的方式,完成输入的操作,完成读的操作(硬盘 --> 内存)
方法:

  • int read(byte[] b) 一次最多读取 b.length 个字节。
    减少硬盘与内存的交互,提高程序的执行效率。
public class FileInputStreamTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            // 创建文件字节输入流对象
            // 文件路径 E:\Users\DIY\IdeaProjects\JavaSE\567\temp
            // 在IDEA中默认的当前路径是Project的根
            //FileInputStream fis = new FileInputStream("E:\\Users\\DIY\\IdeaProjects\\JavaSE\\567\\temp");
            // 也可以这样写
            fis = new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp");

            // 读
            /*int readData = fis.read();  // 这个方法返回的是:读取到的字节本身
            System.out.println(readData);   //97*/

            /*while (true) {
                int read = fis.read();
                if (read == -1) break;
                System.out.println(read);   // 97 98 99
            }*/

            /*int readData = 0;
            while ((readData = fis.read()) !=-1) {
                System.out.println(readData);   //97 98 99
            }*/

            // 采用byte数组,一次读取多个字节,最多读取"数组.length"个字节。
            byte[] bytes = new byte[2];
            /*int readCount = fis.read(bytes);// 这个方法返回的是:读取到的字节数量
            System.out.println(readCount);  //2 读取ab
            // 将字节数组全部转换成字符串
            System.out.println(new String(bytes));  //ab
            // 应该是读到多少转换多少
            System.out.println(new String(bytes,0,readCount));  //ab

            readCount = fis.read(bytes);
            System.out.println(readCount);  //1 读取c
            System.out.println(new String(bytes));  //cb
            System.out.println(new String(bytes,0,readCount));  //c

            readCount = fis.read(bytes);
            System.out.println(readCount);  //-1 没有读到*/

            int readCount = 0;
            while ((readCount = fis.read(bytes)) !=-1) {
                System.out.print(new String(bytes,0,readCount));    //abc
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {  // 避免空指针异常
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

其他常用方法:

  • int available() 返回流当中剩余的没有读到的字节数量
  • long skip(long n) 跳过几个字节不读
public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            // 创建文件字节输入流对象
            // 文件路径 E:\Users\DIY\IdeaProjects\JavaSE\567\temp
            fis = new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp");
            System.out.println("总字节数" + fis.available());   //3

            /*int readByte = fis.read();
            // int available() 返回流当中剩余的没有读到的字节数量
            System.out.println("剩下" + fis.available() + "字节没读"); //2*/

            /*byte[] bytes = new byte[fis.available()];   // 这种方式不适合太大的文件,因为byte数组不能太大
            fis.read(bytes); // 只需要读一次
            System.out.println(new String(bytes));  //abc*/

            // long skip(long n) 跳过几个字节不读
            fis.skip(1);    // 跳过1个不读
            System.out.println(fis.read()); // 98
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {  // 避免空指针异常
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

java.io.FileOutputStream(重点)

文件字符输出流,负责写。
从内存到硬盘

public class FileOutputStreamTest {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            // 文件不存在会新建
            // 这种方式会将原文件清空再重新写入
            //fos = new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp1");
            // 这种方式以追加的方式在文件末尾写入,不会清空原文件内容
            fos = new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp1", true);

            // 写
            byte[] bytes = {97,98,99,100};
            // 将byte数组全部写出
            fos.write(bytes);   // abcd
            // 将byte数组的一部分写出
            fos.write(bytes, 0 ,2); // 追加ab

            String s = "我是中国人";
            // 将字符串转换成byte数组
            byte[] bytes1 = s.getBytes();
            fos.write(bytes1);

            // 写完之后,最后一定要刷新
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

java.io.FileReader

文件字符输入流,只能读取普通文本。
读取文本内容时,比较方便、快捷。
用法跟FileInputStream差不多

public class FileReaderTest {
    public static void main(String[] args) {
        FileReader reader = null;
        try {
            // 创建文件字符输入流
            reader = new FileReader("E:/Users/DIY/IdeaProjects/JavaSE/567/temp1");
            // 读
            char[] chars = new char[3]; //一次读取3个支付
            int readCount = 0;
            while ((readCount = reader.read(chars)) != -1) {
                System.out.print(new String(chars,0,readCount));  //abcdab我是中国人
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

java.io.FileInWhiter

文件字符输出流。写。
只能输出普通文本 用法跟FileOutputStream差不多

public class FileWriterTest {
    public static void main(String[] args) {
        FileWriter fileWriter = null;
        try {
            // 创建文件字符输出流
            //fileWriter = new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/temp3");
            // 不清空,直接进行追加
            fileWriter = new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/temp3",true);

            // 写
            char[] chars = {'你','好','世','界'};
            fileWriter.write(chars);    //你好世界
            fileWriter.write(chars, 2, 2);  //你好世界世界

            fileWriter.write("你好呀");    //你好世界世界你好呀

            // 刷新
            fileWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

文件拷贝
使用 FileReader + FileWriter 进行拷贝。
只能拷贝普通文本

public class CopyTest {
    public static void main(String[] args) {
        FileReader reader = null;
        FileWriter writer = null;
        try {
            // 创建文件字符输入流
            reader = new FileReader("E:/Users/DIY/IdeaProjects/JavaSE/567/File.java");
            // 创建文件字符输出流
            writer = new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java");

            char[] chars = new char[1024 * 512];    //1MB
            int readCount = 0;
            while ((readCount = reader.read(chars)) != -1) {
                writer.write(chars,0,readCount);
            }

            // 刷新
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

转换流

java.io.InputStreamReader

将输入字节流转换成输入字符流

java.io.OutputStreamReader

将输出字节流转换成输出字符流

缓冲流专属

java.io.BufferedReader

带有缓冲区的字符输入流。
使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓冲

public class BufferedReaderTest {
    public static void main(String[] args) throws Exception {
        // 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流
        // 外部负责包装的这个流叫做:包装流,又叫处理流
        // 以下来说,FileReader就是一个节点流,BufferedReader就是包装流
        /*FileReader reader = new FileReader("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java");
        BufferedReader br = new BufferedReader(reader);*/
        
        /*// 字节流
        FileInputStream fis = new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java");
        // 通过转换流转换(InputStreamReader 将字节流转换成字符流)
        // fis 是节点流,reader 是包装流。
        InputStreamReader reader = new InputStreamReader(fis);
        // 这个构造方法只能传一个字符流。不能传字节流
        // reader 是节点流,br 是包装流。
        BufferedReader br = new BufferedReader(reader);*/

        // 合并
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java")));

        // 读一行
        /*System.out.println(br.readLine());  //package com.xxx.javase.filewriter;
        System.out.println(br.readLine());  //
        System.out.println(br.readLine());  //public class File {*/
        String s = null;
        while ((s = br.readLine()) != null) {
            System.out.println(s);
        }

        // 关闭流
        // 对于包装流来说,只需要关闭最外层的流就行,里面的节点流会自动关闭。
        /* //源码如下
            public BufferedReader(Reader in) {
                this(in, defaultCharBufferSize);
            }
            public void close() throws IOException {
                synchronized (lock) {
                    if (in == null) return;
                    try {
                        in.close();
                    } finally {
                        in = null;
                        cb = null;
                    }
                }
            }
        */
        br.close();
    }
}

java.io.BufferedWriter

带有缓冲区的字符输出流

public class BufferedWriterTest {
    public static void main(String[] args) throws Exception {
        // 带有缓冲区的字符输出流
        //BufferedWriter bw = new BufferedWriter(new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java"));
        // 将字符流转换成字节流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java",true)));


        // 写
        bw.write("hello");
        bw.write("\n");
        bw.write("would");
        // 刷新
        bw.flush();
        // 关闭流
        bw.close();
    }
}

java.io.BufferedInputStream

与BufferedReader用法类似

java.io.BufferedOutputStream

与BufferedWriter用法类似

数据流专属

java.io.DataInputStream

DataOutputStream写的文件,只能使用DataInputStream去读。并且要提前知道写入的顺序,读的顺序需要和写的顺序一致,才可以正常取出数据。

public class DataInputStreamTest {
    public static void main(String[] args) throws Exception {
        DataInputStream dis = new DataInputStream(new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/data"));
        // 读
        byte b = dis.readByte();
        short s = dis.readShort();
        int i = dis.readInt();
        long l = dis.readLong();
        float f = dis.readFloat();
        double d = dis.readDouble();
        boolean bl = dis.readBoolean();
        char c = dis.readChar();

        System.out.println(b);  //10
        System.out.println(s);  //20
        System.out.println(i);  //30
        System.out.println(l);  //40
        System.out.println(f);  //1.0
        System.out.println(d);  //3.14
        System.out.println(bl); //false
        System.out.println(c);  //a

        dis.close();
    }
}

java.io.DataOutputStream

这个流可以将数据连同数据的类型一并写入文件。
注意:这个文件不是普通文本文档(用记事本打不开)。

public class DataOutputStreamTest {
    public static void main(String[] args) throws Exception {
        // 创建数据专属的字节输出流
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/data"));

        byte b = 10;
        short s = 20;
        int i = 30;
        long l = 40L;
        float f = 1.0F;
        double d = 3.14;
        boolean sex = false;
        char c = 'a';
        // 写数据
        dos.writeByte(b);
        dos.writeShort(s);
        dos.writeInt(i);
        dos.writeLong(l);
        dos.writeFloat(f);
        dos.writeDouble(d);
        dos.writeBoolean(sex);
        dos.writeChar(c);

        // 刷新
        dos.flush();
        // 关闭
        dos.close();
    }
}

标准输出流

java.io.PrintWriter

java.io.PrintStream(重点)

/*
java.io.PrintStream:标准的字节输出流。默认输出到控制台。
 */
public class PrintStreamTest {
    public static void main(String[] args) throws Exception {
        // 联合起来写
        System.out.println("hello world!");
        // 分开写
        PrintStream ps = System.out;
        ps.println("hello world1");

        // 标准输出流不需要手动close()关闭。
        // 可以改变标准输出流的输出方向

        // 标准输出流不指向控制台,指向"log"文件
        PrintStream printStream = new PrintStream(new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/log"));
        // 修改输出方向,将输出方向修改到"log"文件
        System.setOut(printStream);
        // 再输出
        System.out.println("hello world2");
    }
}

对象专属流:


java.io.ObjectInputStream(重点)

java.io.ObjectOutputStream(重点)

java.io.File类

File类的常用方法

/*
File对象代表文件和目录路径名的抽象表示形式。
 */
public class FileTest {
    public static void main(String[] args) throws IOException {
        File file = new File("E:\\file");
        // 判断是否存在
        System.out.println(file.exists());
        // 如果D:\file不存在,则以文件的形式创建出来
        /*if (!file.exists()) {
            file.createNewFile();
        }*/

        // 如果D:\file不存在,则以目录的形式创建出来
        /*if (!file.exists()) {
            file.mkdir();
        }*/

        File file1 = new File("E:/a/s/d");
        // 以多重目录的形式创建
        /*if (!file1.exists()) {
            file1.mkdirs();
        }*/

        File file2 = new File("E:\\Users\\DIY\\IdeaProjects\\JavaSE\\567\\temp");

        // 获取文件名
        System.out.println("获取文件名:" + file2.getName()); //temp
        // 判断是否是一个目录
        System.out.println(file2.isDirectory());    //false
        // 判断是否是一个文件
        System.out.println(file2.isFile()); //true

        // 获取文件最后一次修改时间
        long millisecond = file2.lastModified();    //返回的是从1970年到现在的总毫秒数
        // 将总毫秒数转换成日期
        Date data = new Date(millisecond);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String strTime = sdf.format(data);
        System.out.println(strTime);    //2022-04-08 10:26:24 105

        // 获取文件大小
        System.out.println(file2.length() + "字节"); //3字节

        // 获取文件的父路径
        System.out.println(file2.getParent());  //E:\Users\DIY\IdeaProjects\JavaSE\567
        File parentFile = file2.getParentFile();
        System.out.println("获取绝对路径:" + parentFile.getAbsolutePath()); //E:\Users\DIY\IdeaProjects\JavaSE\567

        File file3 = new File("temp1");
        // 获取绝对路径
        System.out.println("获取绝对路径:" + file3.getAbsolutePath());    //E:\Users\DIY\IdeaProjects\JavaSE\530\temp1

        File file4 = new File("E:\\Users\\DIY\\IdeaProjects\\JavaSE\\567");
        // File[] listFiles() 获取当前目录下所有的子文件
        File[] files = file4.listFiles();
        // 遍历
        for (File file5 : files) {
            // 获取绝对路径
            //System.out.println(file5.getAbsolutePath());
            // 获取文件名
            System.out.println(file5.getName());
        }
    }
}