详解Java中的“IO流”

按功能来分为输入流和输出流;按类型来分为字节流和字符流。

Java中的流都是从下面四个抽象基类中派生出来的:

  • InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流;
  • OutputStream/Writer:所有输出流的基类前者是字节输出流,后者是字符输出流。

一 、字节流

以字节为单位进行数据传输(8位),适用于处理二进制数据或者未经字符编码的文本数据。

InputStream字节输入流

InputStream 是 Java 中用于处理字节输入流的抽象类。它是所有字节输入流类的父类,提供了一些基本的方法来读取字节数据。

以下是 InputStream 类的一些主要方法和说明:

  1. int read()

    • 从输入流中读取下一个字节的数据,并返回读取的字节(0~255之间的整数值),如果已经到达输入流的末尾,则返回 -1。
    • 如果读取的字节为负数,则表示字节数据的最高位为 1,需要转换为无符号整数才能正确表示字节的值。
  2. int read(byte[] b)

    • 从输入流中读取多个字节的数据,并将其存储到字节数组 b 中。
    • 返回实际读取的字节数,如果已经到达输入流的末尾,则返回 -1。
  3. int read(byte[] b, int off, int len)

    • 从输入流中读取多个字节的数据,并将其存储到字节数组 b 中,从偏移量 off 开始存储,最多读取 len 个字节。
    • 返回实际读取的字节数,如果已经到达输入流的末尾,则返回 -1。
  4. long skip(long n)

    • 跳过输入流中的 n 个字节,返回实际跳过的字节数。
    • 注意:该方法不保证一定成功跳过 n 个字节,可能会跳过比 n 少的字节数。
  5. int available()

    • 返回可以从输入流中读取而不受阻塞的字节数。
    • 注意:available() 方法返回的字节数可能不准确,不应该用于检查是否已经读取完所有的数据。
  6. void close()

    • 关闭输入流并释放与之相关的资源。

以下是一个简单的示例代码,演示如何使用 InputStream 来读取文件中的字节数据:

import java.io.*;

public class InputStreamExample {
    public static void main(String[] args) {
        try {
            // 创建一个 FileInputStream 对象来读取文件
            InputStream inputStream = new FileInputStream("example.txt");

            // 读取文件中的字节数据
            int data;
            while ((data = inputStream.read()) != -1) {
                // 将读取的字节数据转换为字符并打印出来
                System.out.print((char) data);
            }

            // 关闭输入流
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们使用 FileInputStream 来创建一个 InputStream 对象,然后通过 read() 方法逐个字节地读取文件中的数据,直到到达文件末尾(read() 方法返回 -1)。每次读取到一个字节后,我们将其转换为字符并打印出来。

需要注意的是,在实际开发中,应该始终在使用完毕后关闭输入流,以释放相关资源。因此,我们在 finally 块中调用 close() 方法来关闭输入流,以确保即使发生异常,输入流也能够被正确关闭。

InputStream 是一个抽象类,不能直接实例化,常用的实现类包括:

  • FileInputStream:用于从文件中读取数据。
  • ByteArrayInputStream:用于从内存中的字节数组读取数据。
  • BufferedInputStream:提供了缓冲功能,提高了读取效率。
  • DataInputStream:用于从输入流中按照基本数据类型进行数据读取。
import java.io.*;

public class InputStream示例 {
    public static void main(String[] args) {
        try {
            // FileInputStream: 从文件读取数据
            FileInputStream fileInputStream = new FileInputStream("example.txt");
            int byteRead;
            System.out.println("使用FileInputStream从文件中读取数据:");
            while ((byteRead = fileInputStream.read()) != -1) {
                System.out.print((char) byteRead);
            }
            fileInputStream.close();

            // ByteArrayInputSteam: 从字节数组读取数据
            byte[] byteArray = { 65, 66, 67, 68, 69 };
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
            System.out.println("\n\n使用ByteArrayInputStream从字节数组中读取数据:");
            int byteReadFromByteArray;
            while ((byteReadFromByteArray = byteArrayInputStream.read()) != -1) {
                System.out.print((char) byteReadFromByteArray);
            }
            byteArrayInputStream.close();

            // BufferedInputStream: 带缓冲地从文件读取数据
            FileInputStream fileInputStream2 = new FileInputStream("example.txt");
            BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream2);
            System.out.println("\n\n使用BufferedInputStream从文件中读取数据:");
            int byteReadBuffered;
            while ((byteReadBuffered = bufferedInputStream.read()) != -1) {
                System.out.print((char) byteReadBuffered);
            }
            bufferedInputStream.close();

            // DataInputStream: 从文件读取基本数据类型
            FileInputStream fileInputStream3 = new FileInputStream("example.txt");
            DataInputStream dataInputStream = new DataInputStream(fileInputStream3);
            System.out.println("\n\n使用DataInputStream从文件中读取数据类型:");
            System.out.println("整数: " + dataInputStream.readInt());
            System.out.println("双精度数: " + dataInputStream.readDouble());
            dataInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中:

  • 使用 FileInputStream 从文件 (example.txt) 中读取数据。
  • 使用 ByteArrayInputStream 从字节数组 (byteArray) 中读取数据。
  • 使用 BufferedInputStream 带缓冲地从文件读取数据,这提高了效率。
  • 使用 DataInputStream 从文件中读取基本数据类型。请注意,这需要文件以兼容的格式使用 DataOutputStream 写入。

OutputStream字节输出流

OutputStream 是 Java 中用于处理字节输出流的抽象类。它是所有字节输出流类的父类,提供了一些基本的方法来写入字节数据。

以下是 OutputStream 类的一些主要方法和说明:

  1. void write(int b)

    • 将指定的字节写入输出流。
    • 参数 b 是要写入的字节的整数表示,只写入 b 的最低 8 位。
  2. void write(byte[] b)

    • 将字节数组 b 中的所有字节写入输出流。
  3. void write(byte[] b, int off, int len)

    • 将字节数组 b 中从偏移量 off 开始的 len 个字节写入输出流。
  4. void flush()

    • 刷新输出流,强制将缓冲区中的数据写入目的地。
    • 在某些输出流中(如缓冲流),数据可能会被缓冲,调用 flush() 方法可以确保数据被写入。
  5. void close()

    • 关闭输出流并释放与之相关的资源。
import java.io.*;

public class OutputStreamExample {
    public static void main(String[] args) {
        try {
            // 创建一个 FileOutputStream 对象来写入文件
            OutputStream outputStream = new FileOutputStream("example.txt");

            // 写入字符数据到文件
            String data = "Hello, World!";
            byte[] bytes = data.getBytes(); // 将字符串转换为字节数组
            outputStream.write(bytes); // 写入字节数组到输出流

            // 刷新输出流,确保数据被写入文件
            outputStream.flush();

            // 关闭输出流
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们使用 FileOutputStream 来创建一个 OutputStream 对象,然后通过 write(byte[] b) 方法将字节数组中的数据写入文件中。我们首先将字符串转换为字节数组,然后调用 write() 方法将字节数组写入输出流。

最后,我们调用 flush() 方法来刷新输出流,确保所有数据都被写入文件,并在 finally 块中调用 close() 方法来关闭输出流,以释放相关资源。

OutputStream 是一个抽象类,不能直接实例化,常用的实现类包括:

  • FileOutputStream:用于向文件中写入数据。
  • ByteArrayOutputStream:用于向内存中的字节数组写入数据。
  • BufferedOutputStream:提供了缓冲功能,提高了写入效率。
  • DataOutputStream:用于向输出流中按照基本数据类型进行数据写入。

下面是一个示例代码,演示了如何使用这些输出流类:

import java.io.*;

public class OutputStream示例 {
    public static void main(String[] args) {
        try {
            // FileOutputStream: 向文件中写入数据
            FileOutputStream fileOutputStream = new FileOutputStream("example.txt");
            String dataToFile = "Hello, World!";
            fileOutputStream.write(dataToFile.getBytes()); // 写入字符串到输出流
            fileOutputStream.close();

            // ByteArrayOutputStream: 向内存中的字节数组写入数据
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            String dataToByteArray = "Welcome to Java!";
            byteArrayOutputStream.write(dataToByteArray.getBytes()); // 写入字符串到字节数组
            byte[] byteArray = byteArrayOutputStream.toByteArray(); // 获取写入的字节数组
            System.out.println("从内存中的字节数组读取的数据: " + new String(byteArray));
            byteArrayOutputStream.close();

            // BufferedOutputStream: 提供了缓冲功能,提高了写入效率
            FileOutputStream fileOutputStream2 = new FileOutputStream("example.txt");
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream2);
            String dataToBufferedStream = "BufferedOutputStream示例";
            bufferedOutputStream.write(dataToBufferedStream.getBytes()); // 写入字符串到缓冲输出流
            bufferedOutputStream.close();

            // DataOutputStream: 向输出流中按照基本数据类型进行数据写入
            FileOutputStream fileOutputStream3 = new FileOutputStream("data.dat");
            DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream3);
            int intValue = 123;
            double doubleValue = 456.789;
            dataOutputStream.writeInt(intValue); // 写入整数到输出流
            dataOutputStream.writeDouble(doubleValue); // 写入双精度数到输出流
            dataOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中:

  • 使用 FileOutputStream 向文件 (example.txt) 中写入数据。
  • 使用 ByteArrayOutputStream 向内存中的字节数组写入数据,并将其转换为字符串输出。
  • 使用 BufferedOutputStream 提供了缓冲功能,以提高写入效率,示例中写入了一个字符串到文件中。
  • 使用 DataOutputStream 向输出流中按照基本数据类型进行数据写入,并将其保存到文件 (data.dat) 中。

二、字符流

以字符为单位进行数据传输 ,适用于处理文本数据,并能按照指定字符编码进行转换。

Reader字符输入流

Reader 是 Java 中用于处理字符输入流的抽象类。它是所有字符输入流类的父类,提供了一些基本的方法来读取字符数据。

以下是 Reader 类的一些主要方法和说明:

  1. int read()

    • 读取输入流中的下一个字符,并返回其 Unicode 值(0~65535),如果已经到达输入流的末尾,则返回 -1。
    • 如果读取的字符为负数,则表示到达了输入流的末尾。
  2. int read(char[] cbuf)

    • 从输入流中读取多个字符,并将其存储到字符数组 cbuf 中。
    • 返回实际读取的字符数,如果已经到达输入流的末尾,则返回 -1。
  3. int read(char[] cbuf, int off, int len)

    • 从输入流中读取多个字符,并将其存储到字符数组 cbuf 中,从偏移量 off 开始存储,最多读取 len 个字符。
    • 返回实际读取的字符数,如果已经到达输入流的末尾,则返回 -1。
  4. long skip(long n)

    • 跳过输入流中的 n 个字符,返回实际跳过的字符数。
    • 注意:该方法不保证一定成功跳过 n 个字符,可能会跳过比 n 少的字符。
  5. void close()

    • 关闭输入流并释放与之相关的资源。
import java.io.*;

public class ReaderExample {
    public static void main(String[] args) {
        try {
            // 创建一个 FileReader 对象来读取文件
            Reader reader = new FileReader("example.txt");

            // 读取文件中的字符数据
            int data;
            while ((data = reader.read()) != -1) {
                // 将读取的字符数据转换为字符并打印出来
                System.out.print((char) data);
            }

            // 关闭输入流
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们使用 FileReader 来创建一个 Reader 对象,然后通过 read() 方法逐个字符地读取文件中的数据,直到到达文件末尾(read() 方法返回 -1)。每次读取到一个字符后,我们将其转换为字符并打印出来。

与之前的示例类似,我们在 finally 块中调用 close() 方法来关闭输入流,以确保资源得到正确释放。

Reader 是一个抽象类,不能直接实例化,常用的实现类包括:

  • FileReader:用于从文件中读取字符数据。
  • CharArrayReader:用于从字符数组中读取字符数据。
  • BufferedReader:提供了缓冲功能,提高了读取效率,并且可以按行读取数据。
  • InputStreamReader:可以将字节输入流转换为字符输入流,同时指定字符编码。

以下是使用这些字符输入流类的示例代码:

import java.io.*;

public class Reader示例 {
    public static void main(String[] args) {
        try {
            // FileReader: 从文件中读取字符数据
            FileReader fileReader = new FileReader("example.txt");
            int charRead;
            System.out.println("使用FileReader从文件中读取数据:");
            while ((charRead = fileReader.read()) != -1) {
                System.out.print((char) charRead);
            }
            fileReader.close();

            // CharArrayReader: 从字符数组中读取字符数据
            char[] charArray = {'A', 'B', 'C', 'D', 'E'};
            CharArrayReader charArrayReader = new CharArrayReader(charArray);
            System.out.println("\n\n使用CharArrayReader从字符数组中读取数据:");
            int charReadFromArray;
            while ((charReadFromArray = charArrayReader.read()) != -1) {
                System.out.print((char) charReadFromArray);
            }
            charArrayReader.close();

            // BufferedReader: 带缓冲地从文件读取数据,提高了读取效率,并且可以按行读取数据
            FileReader fileReader2 = new FileReader("example.txt");
            BufferedReader bufferedReader = new BufferedReader(fileReader2);
            System.out.println("\n\n使用BufferedReader从文件中读取数据:");
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }
            bufferedReader.close();

            // InputStreamReader: 将字节输入流转换为字符输入流,同时指定字符编码
            FileInputStream fileInputStream = new FileInputStream("example.txt");
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
            System.out.println("\n\n使用InputStreamReader从字节输入流中读取数据:");
            int charReadFromInputStream;
            while ((charReadFromInputStream = inputStreamReader.read()) != -1) {
                System.out.print((char) charReadFromInputStream);
            }
            inputStreamReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中:

  • 使用 FileReader 从文件 (example.txt) 中读取字符数据。
  • 使用 CharArrayReader 从字符数组 (charArray) 中读取字符数据。
  • 使用 BufferedReader 提供了缓冲功能,以提高读取效率,并且按行读取数据。
  • 使用 InputStreamReader 将字节输入流转换为字符输入流,同时指定字符编码(这里指定为 UTF-8)。

Writer字符输出流 

Writer 是 Java 中用于处理字符输出流的抽象类。它是所有字符输出流类的父类,提供了一些基本的方法来写入字符数据。

以下是 Writer 类的一些主要方法和说明:

  1. void write(int c)

    • 将指定的字符写入输出流。
  2. void write(char[] cbuf)

    • 将字符数组 cbuf 中的所有字符写入输出流。
  3. void write(char[] cbuf, int off, int len)

    • 将字符数组 cbuf 中从偏移量 off 开始的 len 个字符写入输出流。
  4. void write(String str)

    • 将字符串 str 中的所有字符写入输出流。
  5. void write(String str, int off, int len)

    • 将字符串 str 中从偏移量 off 开始的 len 个字符写入输出流。
  6. void flush()

    • 刷新输出流,强制将缓冲区中的数据写入目的地。
    • 在某些输出流中(如缓冲流),数据可能会被缓冲,调用 flush() 方法可以确保数据被写入。
  7. void close()

    • 关闭输出流并释放与之相关的资源。
import java.io.*;

public class WriterExample {
    public static void main(String[] args) {
        try {
            // 创建一个 FileWriter 对象来写入文件
            Writer writer = new FileWriter("example.txt");

            // 写入字符数据到文件
            String data = "Hello, World!";
            writer.write(data); // 写入字符串到输出流

            // 刷新输出流,确保数据被写入文件
            writer.flush();

            // 关闭输出流
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们使用 FileWriter 来创建一个 Writer 对象,然后通过 write(String str) 方法将字符串写入文件中。我们直接调用 write() 方法将字符串写入输出流。

最后,我们调用 flush() 方法来刷新输出流,确保所有数据都被写入文件,并在 finally 块中调用 close() 方法来关闭输出流,以释放相关资源。

Writer 是一个抽象类,不能直接实例化,常用的实现类包括:

  • FileWriter:用于向文件中写入字符数据。
  • CharArrayWriter:用于向字符数组中写入字符数据。
  • BufferedWriter:提供了缓冲功能,提高了写入效率,并且可以按行写入数据。
  • OutputStreamWriter:可以将字节输出流转换为字符输出流,同时指定字符编码。

以下是使用这些字符输出流类的示例代码:

import java.io.*;

public class Writer示例 {
    public static void main(String[] args) {
        try {
            // FileWriter: 向文件中写入字符数据
            FileWriter fileWriter = new FileWriter("example.txt");
            String dataToFile = "Hello, World!";
            fileWriter.write(dataToFile); // 写入字符串到输出流
            fileWriter.close();

            // CharArrayWriter: 向字符数组中写入字符数据
            CharArrayWriter charArrayWriter = new CharArrayWriter();
            String dataToCharArray = "Welcome to Java!";
            charArrayWriter.write(dataToCharArray); // 写入字符串到字符数组
            char[] charArray = charArrayWriter.toCharArray(); // 获取写入的字符数组
            System.out.println("从字符数组中读取的数据: " + new String(charArray));
            charArrayWriter.close();

            // BufferedWriter: 提供了缓冲功能,提高了写入效率,并且可以按行写入数据
            FileWriter fileWriter2 = new FileWriter("example.txt");
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter2);
            String dataToBufferedStream = "BufferedWriter示例";
            bufferedWriter.write(dataToBufferedStream); // 写入字符串到缓冲输出流
            bufferedWriter.close();

            // OutputStreamWriter: 将字节输出流转换为字符输出流,同时指定字符编码
            FileOutputStream fileOutputStream = new FileOutputStream("example.txt");
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
            String dataToOutputStream = "OutputStreamWriter示例";
            outputStreamWriter.write(dataToOutputStream); // 写入字符串到输出流
            outputStreamWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中:

  • 使用 FileWriter 向文件 (example.txt) 中写入字符数据。
  • 使用 CharArrayWriter 向字符数组中写入字符数据,并将其转换为字符串输出。
  • 使用 BufferedWriter 提供了缓冲功能,以提高写入效率,并且示例中写入了一个字符串到文件中。
  • 使用 OutputStreamWriter 将字节输出流转换为字符输出流,并指定字符编码(这里指定为 UTF-8)。

三、 信息存储最小单位都是字节,那为什么IO流要分为字节流和字符流呢?

因为字节流如果我们不知道编码的话就容易乱码,所有干脆提供了一个直接操作字符的接口

常见编码:

utf8 :英文占 1 字节,中文占 3 字节;

unicode:任何字符都占 2 个字节;

gbk:英文占 1 字节,中文占 2 字节。

 四、打印流

打印流(PrintStream 和 PrintWriter)是 Java 中用于将数据格式化输出到目的地的类,它们提供了方便的方法来打印各种数据类型的值,并且可以自动刷新缓冲区。

  1. PrintStream

    • PrintStream 是处理字节流的打印类,可以向输出流打印各种数据类型的值,并且支持自动刷新缓冲区。
    • 常见的构造方法包括:
      • PrintStream(OutputStream out):使用指定的输出流创建 PrintStream 对象。
      • PrintStream(String fileName):使用指定的文件名创建 PrintStream 对象。
  2. PrintWriter

    • PrintWriter 是处理字符流的打印类,功能类似于 PrintStream,但是针对字符流。
    • 常见的构造方法包括:
      • PrintWriter(File file):使用指定的文件创建 PrintWriter 对象。
      • PrintWriter(OutputStream out):使用指定的输出流创建 PrintWriter 对象。
      • PrintWriter(String fileName):使用指定的文件名创建 PrintWriter 对象。

这些类提供了一系列重载的 printprintln 方法,可以用于打印各种类型的数据,并且可以按照格式化的方式进行输出。此外,它们还提供了一些其他的方法,如 formatprintf,用于按照指定的格式输出数据。

下面是一个简单的示例代码,演示了如何使用 PrintStreamPrintWriter 打印数据:

import java.io.*;

public class PrintStreamPrintWriterExample {
    public static void main(String[] args) {
        try {
            // 使用 PrintStream 打印数据到控制台
            PrintStream printStream = new PrintStream(System.out);
            printStream.println("This is a message printed using PrintStream.");
            printStream.printf("The value of pi is: %.2f%n", Math.PI);
            printStream.close();

            // 使用 PrintWriter 打印数据到文件
            PrintWriter printWriter = new PrintWriter("output.txt");
            printWriter.println("This is a message printed using PrintWriter.");
            printWriter.printf("The value of e is: %.4f%n", Math.E);
            printWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们使用 PrintStream 打印数据到控制台,并使用 PrintWriter 打印数据到文件。

  • 15
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

多宝气泡水

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值