Java的IO流

IO流

主要内容

  1. java.io.File类的使用:计算机操作系统中的文件和文件夹

  2. IO原理及流的分类

文件流(数据流的读写都是基于文件的操作)FileInputStream/FileOutputStream/FileReader/FileWriter

缓存流(数据流的读写都是基于内存的操作)

BufferedInputStream/BufferedOutputStream/BufferedReader/BufferedWriter

通过程序把一个图放到某一个文件夹,把图片转化为一个数据集(例如二进制),把这些数据一点一点传到文件夹,这个传递的过程就很类似于水的流动,我们就可以称这个整体的数据集是一个数据流

  1. 转换流

    InputStreamReader/OutputStreamWriter

  2. 标准输入/输出

  3. 打印流(了解)

    PrintStream/PrintWriter

  4. 数据流(了解)

    DataInputStream/DataOutputStream

  5. 对象流===涉及序列化、反序列化(把一个对象转化为一个数据流进行读写)

    ObjectInputStream/ObjectOutputStream

  6. 随机存取文件流(RandomAccessFile)例如一个TXT文件,其中有100行数据,可以直 接读取第50行的数据,也可以在第89行插入数据

    File类

    java.io.File类:文件和目录路径名的抽象表示形式,与平台无关

    File能新建、删除、重命名文件和目录,但File不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流

    File对象可以作为参数传递给流的构造函数

    File类的常见构造方法:

    1. public File(String pathname)

      以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储

    2. public File(String parent,String child)

      以parent为父路径,child为子路径创建File对象

    File的静态属性String separator存储了当前系统的路径分隔符

    在UNIX中,此字段为'/',在Windows中,为'\\'

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

public class Demo01 {
    public static void main(String[] args) {
        File f = new File("D:\\test\\abc\\tt.txt");//这个时候对象f就是tt.txt文件
        File f1 = new File("D:\\test", "abc\\tt.txt");//这个时候对象f1也是tt.txt文件,用的少
        File f2 = new File("D:/test/abc/tt.txt");//这个时候对象f2就是tt.txt文件
        File f3 = new File("D:" + File.separator + "test/abc/tt.txt");//这个时候对象f3就是tt.txt文件
        //注意,\在文件中是路径的分隔符,但是在java编程中一个\的意思是转义符,在java中\\或者/才是文件的分隔符
        System.out.println(f2.getName());//获取文件名
        System.out.println(f.getPath());//获取文件或者文件夹的路径
        File f5 = new File("src/com/aggregate/io");//使用相对路径创建File对象
        System.out.println(f5.getPath());//获取文件或者文件夹的路径,就是new file时候写的路径
        System.out.println(f5.getAbsolutePath());//获取当前文件的绝对路径
        System.out.println(f5);
        System.out.println(f5.getAbsoluteFile());//返回一个用当前文件的路径构建的File对象
        System.out.println(f5.getParent());//返回当前或者文件夹的父级路径
        f.renameTo(new File("D:/test/abc/tt1.txt"));//给文件或者文件夹重命名
        File f6 = new File("D:/test/abc/tt1.txt");
        System.out.println(f6.exists());//判断文件或者文件夹是否存在
        System.out.println(f6.canWrite());//判断文件是否可写
        System.out.println(f6.canRead());//判断文件是否可读
        System.out.println(f6.isFile());//判断当前的file对象是不是文件
        System.out.println(f6.isDirectory());//判断当前的file对象是不是文件夹或者目录
        System.out.println(f6.lastModified());//获取文件的最后修改时间,返回的是一个毫秒数
        System.out.println(f6.length());//返回文件的长度,单位是字节数
        File f7 = new File("D:/test/abc/tt2.txt");
        System.out.println(f7.exists());//判断文件是否存在
        if (!f7.exists()) {
            try {
                f7.createNewFile();//创建新的文件
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        f7.delete();//删除文件
        File f8 = new File("D:/test/abc/cc");
        f8.mkdir();//创建单层目录,如果使用这样的方法来创建多层目录,就得一层一层的执行mkdir()
        File f9 = new File("D:/test/abc/a/b/c");
        f9.mkdirs();//这个方法是直接用来创建多层目录
        File f10 = new File("D:/test");
        String[] list = f10.list();//返回的是当前文件夹的子集的名称,包括目录和文件
        for (String s : list) {
            System.out.println(s);
        }
        File[] files = f10.listFiles();//返回的是当前文件夹的子集的file对象,包括目录和文件
        for (File file : files) {
            System.out.println(file);
        }
        File t = new File("D:/test");
        new Demo01().test(t);
    }
    //遍历d盘下的test文件,把test文件夹下所有的目录与文件全部遍历出来,不论层级有多深,要全部遍历出来
    //这个使用递归的方式来实现

    /**
     * 递归遍历文件
     *
     * @param file
     */
    public void test(File file) {
        if (file.isFile()) {
            System.out.println(file.getAbsoluteFile() + "是文件");
        } else {
            System.out.println(file.getAbsoluteFile() + "是文件夹");
            //如果是文件夹,这个文件夹里就可能有子文件或者文件
            File[] files = file.listFiles();
            if (files != null && files.length > 0) {
                for (File file1 : files) {
                    test(file1);//递归
                }
            }

        }
    }
}

Java IO原理

IO流用来处理设备之间的数据传输

Java程序中,对于数据的输入/输出操作以“流(stream)”的方式进行

java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据

输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。

输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中

流的分类

按操作数据单位不同分为:字节流(8bit),字符流(16bit)

按数据流的流向不同分为:输入流、输出流

按流的角色的不同分为:节点流,处理流

image-20210703182234596

Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

IO流体系

image-20210703182616864

文件字节输入流

文件字节输出流

package com.aggregate.io;

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Demo02 {
    public static void main(String[] args) {
        Demo02.testFileInputStream();
        Demo02.testFileOutputStream();
        Demo02.copyFile("D:\\test\\abc\\tt1.txt","D:\\test\\abc\\a\\tt4.txt");
        Demo02.copyFile("D:\\test\\abc\\img.png","D:\\test\\abc\\a\\img.png");
    }

    /**
     * 文件字节输入流FileInputStream
     */
    public static void testFileInputStream() {
        try {
            FileInputStream fileInputStream = new FileInputStream("D:\\test\\abc\\tt1.txt");
            byte[] b = new byte[1024];//设置有关byte数组接收读取文件的内容
            int len = 0;//设置一个读取数据的长度
            //fileInputStream.read(b);//将txt文件中的内容读取到b中
            //fileInputStream.read()方法有一个返回值,返回值是读取的数据的长度,如果读取到最后一个数据,还会向后读一个
            //也就意味着当fileInputStream.read()的返回值是-1的时候整个文件就读取完毕了
            while ((len = fileInputStream.read(b)) != -1) {
                //参数1:缓存数据的数组;参数2:是从数组的哪个位置开始转化字符串;参数3:是总共转化几个字节
                System.out.println(new String(b, 0, len));//将流byte转换为字符串输出
            }

            fileInputStream.close();//注意。流在使用完毕之后一定要关闭

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

    }

    /**
     * 文件字节输出流FileOutputStream
     */
    public static void testFileOutputStream() {
        try {
            //指定向tt4输出数据
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\test\\abc\\tt4.txt");
            String str = "advantages";
            fileOutputStream.write(str.getBytes());//把数据写到内存中
            fileOutputStream.flush();//把内存中的数据刷写到硬盘
            fileOutputStream.close();

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

    /**
     * 复制文件到指定位置
     **/
    public static void copyFile(String inPath, String outPath) {
        try {
            //读取的源文件
            FileInputStream fileInputStream = new FileInputStream(inPath);
            //复制到哪里
            FileOutputStream fileOutputStream = new FileOutputStream(outPath);
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = fileInputStream.read(b)) != -1) {
                fileOutputStream.write(b, 0, len);
            }
            fileOutputStream.flush();
            fileOutputStream.close();
            fileOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意

文件字节流非常通用,可以用来操作字符的文档,还可以操作任何的其他类型文件(图片,压缩包等等),引用字节流直接使用二进制

文件字符输入流

文件字符输出流

package com.aggregate.io;

import com.sun.org.apache.xalan.internal.xsltc.dom.StepIterator;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) {
        Demo03.testFileReader("D:\\test\\abc\\tt1.txt");
        Demo03.testFileWriter("hello world", "D:\\test\\abc\\tt5.txt");
        Demo03.copyFile("D:\\test\\abc\\tt5.txt", "D:\\test\\abc\\cc\\tt5.txt");
    }

    /**
     * 文件字符输入流FileReader
     */
    public static void testFileReader(String inPath) {
        try {
            //创建文件字符输入流的对象
            FileReader fileReader = new FileReader(inPath);
            char[] c = new char[1024];//创建临时存数据的字符数组
            int len = 0;
            while ((len = fileReader.read(c)) != -1) {
                System.out.println(new String(c, 0, len));
            }
            fileReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件字符输出流FileWriter
     */
    public static void testFileWriter(String text, String outPath) {
        try {
            FileWriter fileWriter = new FileWriter(outPath);
            fileWriter.write(text);//写到内存中
            fileWriter.flush();//把内存的数据刷到硬盘
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 字符流完成拷贝文件
     * 字符流自适合内容是字符的文件
     *
     * @param inPath
     * @param outPath
     */
    public static void copyFile(String inPath, String outPath) {
        try {
            FileReader fileReader = new FileReader(inPath);
            FileWriter fileWriter = new FileWriter(outPath);
            char[] c = new char[1024];
            int len = 0;
            while ((len = fileReader.read()) != -1) {//读取数据
                fileWriter.write(c, 0, len);//写入数据到内存
            }
            fileWriter.flush();
            fileWriter.close();
            fileReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意

  • 定义文件路径时,注意:可以用“/”或者“\”
  • 在写入一个文件时,如果目录下有同名文件将被覆盖
  • 在读取文件时,必须保证该文件已存在,否则出异常

处理流之一:缓冲流

为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组

根据数据操作单位可以把缓冲流分为

BufferedInputStream和BufferedOutputStream

BufferedReader和BudderedWriter

缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法

对于输出的缓冲流,写出的数据会先在内存中缓冲,使用flush()将会使内存中的数据立刻写出

注意

缓冲流是把数据缓冲到内存中

package com.aggregate.io;

import java.io.*;

public class Demo05 {
    public static void main(String[] args) {
        try {
            Demo05.testBufferedReader();
            Demo05.testBufferedWriter();
            Demo05.copyFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 缓冲字符输入流
     */
    public static void testBufferedReader() throws Exception {
        FileReader fileReader = new FileReader("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        char[] c = new char[1024];
        int len = 0;
        while ((len = bufferedReader.read(c)) != -1) {
            System.out.println(new String(c, 0, len));
        }
        bufferedReader.close();
        fileReader.close();
    }

    /**
     * 缓冲字符输出流
     */
    public static void testBufferedWriter() throws Exception {
        FileWriter fileWriter = new FileWriter("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt3.txt");
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        String s = "hello world!!!!!";
        bufferedWriter.write(s);
        bufferedWriter.flush();
        bufferedWriter.close();
        fileWriter.close();
    }

    /**
     * 缓冲字符流复制文件
     */
    public static void copyFile() throws Exception {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt3.txt"));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt4.txt"));
        char[] c = new char[1024];
        int len = 0;
        while ((len = bufferedReader.read(c)) != -1) {
            bufferedWriter.write(c, 0, len);
        }
        bufferedWriter.flush();
        bufferedWriter.close();
        bufferedReader.close();
    }

}

处理流之二:转换流

转换流提供了在字节流和字符流之间的转换

Java API提供了两个转换流:

InputStreamReader和OutputStreamWriter

字节流中的数据都是字符时,转成字符流操作更高效

InputStreamReader

用于将字节流中读取到的字节按指定字符集解码成字符。需要和InputStream"套接"

构造方法:

public InputStreamReader(InputStream in)

public InputStreamReader(InputStream in,String charsetName)

如:Reader isr = new InputStreamReader(System.in,"ISO5334_1");

package com.aggregate.io;

import java.io.*;

/**
 * 转换流
 * 可以把字节流转换为字符流
 * 当字节流中的数据都是字符的时候,使用转换流转为字符流处理效率更高
 */
public class Demo06 {
    public static void main(String[] args) {
        //所有的文件都是有编码格式
        //对于我们来说,txt和java文件一般来讲有三种编码
        //ISO8859-1,西欧编码,是纯粹英文编码,不适应汉字
        //GBK和UTF-8,这两编码是适用于中文和英文
        //一般使用UTF-8编码
        try {
            Demo06.testInputStreamReader();
            Demo06.testOutputStreamWriter();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 转换字节输入流为字符输入流
     * 注意,在转换字符流的时候,设置的字符集编码要与读取的文件的数据的编码一致
     * 不然就会出现乱码
     *
     * @throws FileNotFoundException
     */
    public static void testInputStreamReader() throws Exception {
        FileInputStream fileInputStream = new FileInputStream("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt5.txt");
        //把字节流转换为字符流
        //参数1是字节流,参数2是编码
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
        char[] c = new char[1024];
        int len = 0;
        while ((len = inputStreamReader.read(c)) != -1) {
            System.out.println(new String(c, 0, len));
        }
        inputStreamReader.close();
        fileInputStream.close();
    }

    /**
     * 转换字节输出流为字符输出流
     */
    public static void testOutputStreamWriter() throws Exception {
        FileOutputStream fileOutputStream = new FileOutputStream("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt6.txt");
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
        outputStreamWriter.write("你好,世界!");
        outputStreamWriter.flush();
        outputStreamWriter.close();
        outputStreamWriter.close();
    }
}

处理流之三:标准输入输出流

System.in和System.out分别代表了系统标准的输入和输出设备

默认输入设备是键盘,输出设备是显示器

System.in的类型是InputStream

System.out的类型是PrintStream,其是OutputStream的子类FileOutputStream的子类

练习:把控制台输入的内容写到指定的TXT文件中,当接收到字符串over,就结束程序的运行。

处理流之四:打印流

在整个IO包中,打印流是输出信息最方便的类

PrintStream(字符打印流)和PrintWrite(字符打印流)提供了一系列重载的print和println方法,用于多种数据类型的输出

  • PrintStream和PrintWriter的输出不会抛出异常
  • PrintStream和PrintWriter有自动flush功能
  • Syetem.out返回的是PrintStream的实例

处理流之五:数据流

为了方便地操作Java语言的基本数据类型的数据,可以使用数据流

数据流有两大类:(用于读取和写出基本数据类型的数据)

  • DataInputStream和DataOutputStream分别“套接”在InputStream和OutputStream节点流上

  • DataInputStream中的方法

    boolean readBoolean()

    char readChar()

    double readBoolean()

    long readLong()

    String readUTF()

    byte readByte()

    float readFloat()

    short readShort()

    int readInt()

    void readFully(byte[] b)

  • DataOutputStream中的方法

    将上述的方法的read改为相应的write即可

处理流之六:对象流

ObjectInputStream和ObjectOutputStream

用于存储和读取对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来

序列化:用ObjectInputStream类将一个Java对象写入IO流中

反序列化:用ObjectInputStream类从IO流中恢复该Java对象

ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

例如:

person对象

  1. 把这个对象存到电脑的硬盘上,硬盘存储的基础是什么?是二进制

    那就需要把对象转化为一个二进制的字节流,把这个流保存到电脑上。要使用这个对象,得把流转化为对象再使用

  2. 把这个对象通过网络传到另一台机器上,网络的通信基础是什么?是二进制

    也就是需要把一个对象转化为二进制的数据流,把这个流通过网络进行传输,在接收者如果要使用接收的对象得先把对象的流转化为对象

正是因为保存对象到硬盘(对象的持久化)和对象的网络传输,需要做这两件事,就产生了对象的输入与输出流

序列化与反序列化都针对的是对象的各种属性,不包括类的属性

如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口:

  • Serializable
  • Externalizable

对象序列化

凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量private static final long serialVersionUID;

serialVersionUID用来表明类的不同版本间的兼容性

如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的源代码做了修改,serialVersionUID可能发生变化。故建议,显示声明

显示定义serialVersionUID的用途

  • 希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID
  • 不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID

使用对象流序列化对象

若某个类实现了Seralizable接口,该类的对象就是可序列化的:

  • 创建一个ObjectOutputStream
  • 调用ObjectOutputStream对象的writeObject(对象)方法输出可序列化对象。注意写出一次,操作flush()

反序列化

  • 创建一个ObjectInputStream
  • 调用readObject()方法读取流中的对象

强调:如果某个类的字段不是基本数据类型或String类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的Field的类也不能序列化

package com.aggregate.io;

import java.io.Serializable;

/**
 * 可以序列化与反序列化的对象
 */
public class Person implements Serializable {
    private static final long IL = 0;
    /**
     * 一个表示序列化版本标识符的静态变量
     * 用来表明类的不同版本间的兼容性
     */
    private static final long serialVersionUID = IL;
    String name;
    int age;

}
package com.aggregate.io;


import java.io.*;

/**
 * 序列化与反序列化
 * 注意:对象的序列化与反序列化使用的类要严格一致,包名,类名,类结构等等所有都要一致
 */
public class TestPerson {
    public static void main(String[] args) {
        try {
            TestPerson.testSerialize();
            TestPerson.testDeserialize();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 对象的序列化
     *
     * @throws Exception
     */
    public static void testSerialize() throws Exception {
        //定义对象的输出流,把对象的序列化之后的流放到指定的文件中
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt9.txt"));
        Person p = new Person();
        p.name = "张三";
        p.age = 11;
        //将p序列化
        out.writeObject(p);
        out.flush();
        out.close();
    }

    public static void testDeserialize() throws Exception {
        //创建对象输入流对象,从指定的文件中把对象序列化后的流读取出来
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt9.txt"));
        Object obj = in.readObject();
        Person p = (Person) obj;
        System.out.println(p.name);
        System.out.println(p.age);
        in.close();

    }
}

RandomAccessFile类

RandomAccessFile类支持“随机访问”的方式,程序可以直接跳到文件的任意地方来读、写文件

  • 支持只访问文件的部分内容
  • 可以向已存在的文件后追加内容

RandomAccessFile对象包含一个记录指针,用以标示当前读写处的位置

RandomAccessFile类对象可以自由移动记录指针

  • long getFilePointer():获取文件记录指针的当前位置
  • void seet(long pos):将文件记录指针定位到pos位置

构造器

  • public RandomAccessFile(File file,String mode)
  • public RandomAccessFile(String name,String mode)

创建RandomAccessFile类实例需要指定一个mode参数,该参数指定RandomAccessFile的访问模式:

  • r:以只读方式打开
  • rw:打开以便读取和写入
  • rwd:打开以便读取和写入;同步文件内容的更新
  • rws:打开以便读取和写入;同步文件内容和元数据的更新
package com.aggregate.io;

import java.io.FileNotFoundException;
import java.io.RandomAccessFile;

/**
 * 文件的随机读写
 * 程序可以直接跳到文件的任意地方来读、写文件
 */
public class Demo09 {
    public static void main(String[] args) {
        try {
//            Demo09.testRandomAccessFileRead();
            Demo09.testRandomAccessFileWrite();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 随机读文件
     *
     * @throws Exception
     */
    public static void testRandomAccessFileRead() throws Exception {
        //      RandomAccessFile的构造有两个参数,
        //      参数1是读写的文件的路径
        //      参数2是指定RandomAccessFile的访问模式
        //       - r:以只读方式打开
        //       - rw:打开以便读取和写入
        //       - rwd:打开以便读取和写入;同步文件内容的更新
        //       - rws:打开以便读取和写入;同步文件内容和元数据的更新
        //最常用的是r和rw
        RandomAccessFile ra = new RandomAccessFile("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt10.txt", "r");
        ra.seek(0);//设置读取文件内容的起始点,来达到从文件的任意位置读取
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = ra.read(b)) != -1) {
            System.out.println(new String(b, 0, len));
        }
        ra.close();

    }

    /**
     * 随机写文件
     */
    public static void testRandomAccessFileWrite() throws Exception {
        RandomAccessFile ra = new RandomAccessFile("F:\\code\\Java基础语法\\src\\com\\aggregate\\io\\tt10.txt", "rw");
//        ra.seek(0);//设置写的起始点,0代表从开头写
        //注意:如果是在文件开头或者中间的某个位置开始写的话,就会用写的内容覆盖掉等长度的原内容
        ra.seek(ra.length());//设置写的起始点,ra.length()代表从文件的最后结尾写,也就是文件的追加
        ra.write("你好,世界".getBytes());
        ra.close();
    }
}

流的基本应用小节

流是用来处理数据的

处理数据时,一定要先明确数据源,与数据目的地

数据源可以是文件,也可以是键盘

数据目的地可以是文件、显示器或者其他设备

而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等

重点

  • 字节流-缓冲流

    输入流:InputStream-FileInputStream-BufferedInputStream

    输出流:OutputStream-FileOutputStream-BufferedOutputStream

  • 字符流-缓冲流

    输入流:Reader-FileReader-BufferedReader

    输出流:Writer-FileWriter-BufferedWriter

  • 转换流

    InputStreamReader和OutputStreamWriter

  • 对象流

    ObjectInputStream和ObjectOutputStream

    序列化

    反序列化

  • 随机存取流

    RandomAccessFile

posted @ 2021-07-05 21:25  独爱郑爽  阅读(68)  评论(0)    收藏  举报
Live2D
返回顶端