Java中的I/O流

发布于:2025-07-04 ⋅ 阅读:(15) ⋅ 点赞:(0)

Java中的I/O流

Java中的I/O流(Input/Output Streams)是用于处理输入和输出操作的类。这些流可以用来读取或写入数据,无论是从文件、网络连接还是内存缓冲区。Java I/O API位于java.io包中,并分为字节流和字符流两大类。

字节流

在Java中,字节流主要用于处理以字节为单位的数据输入和输出操作。它们非常适合处理二进制数据,如图像文件、音频文件等,也可以用于文本文件的读写(虽然对于文本文件,通常更推荐使用字符流)。字节流的核心类位于java.io包中,主要包括抽象类InputStream和OutputStream及其子类。

  • InputStream:抽象类,所有字节输入流的超类。
  • OutputStream:抽象类,所有字节输出流的超类。
  • FileInputStream:用于从文件系统中的某个文件中读取字节。
  • FileOutputStream:用于向文件系统中的某个文件写入字节。
  • BufferedInputStreamBufferedOutputStream:通过内部缓冲区提高性能。
  • ByteArrayInputStreamByteArrayOutputStream:在内存中以字节数组的形式存储数据。
  • DataInputStreamDataOutputStream:允许按基本数据类型读写数据。
  • ObjectInputStreamObjectOutputStream:用于序列化和反序列化对象。

1. InputStream(抽象类)

  • 作用:所有字节输入流的超类,定义了从源读取字节的基本方法(如 read())。
  • 使用范围:作为其他字节输入流的基类,不直接实例化。
  • 示例代码
    // 通常通过子类使用,如 FileInputStream
    

2. OutputStream(抽象类)

  • 作用:所有字节输出流的超类,定义了向目标写入字节的基本方法(如 write())。
  • 使用范围:作为其他字节输出流的基类,不直接实例化。
  • 示例代码
    // 通常通过子类使用,如 FileOutputStream
    

3. FileInputStream

  • 作用:从文件系统读取字节数据。
  • 使用范围:需要读取本地文件内容的场景。
  • 示例代码
    try (FileInputStream fis = new FileInputStream("input.txt")) {
        int data;
        while ((data = fis.read()) != -1) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

4. FileOutputStream

  • 作用:向文件系统写入字节数据。
  • 使用范围:需要向本地文件写入内容的场景。
  • 示例代码
    try (FileOutputStream fos = new FileOutputStream("output.txt")) {
        String text = "Hello, World!";
        fos.write(text.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
    

5. BufferedInputStream

  • 作用:通过内部缓冲区提高字节输入流的读取性能。
  • 使用范围:需要高效读取大文件或频繁读取小数据块的场景。
  • 示例代码
    try (FileInputStream fis = new FileInputStream("input.txt");
         BufferedInputStream bis = new BufferedInputStream(fis)) {
        int data;
        while ((data = bis.read()) != -1) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

6. BufferedOutputStream

  • 作用:通过内部缓冲区提高字节输出流的写入性能。
  • 使用范围:需要高效写入大文件或频繁写入小数据块的场景。
  • 示例代码
    try (FileOutputStream fos = new FileOutputStream("output.txt");
         BufferedOutputStream bos = new BufferedOutputStream(fos)) {
        String text = "Hello, Buffered World!";
        bos.write(text.getBytes());
        bos.flush(); // 确保缓冲区数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

7. ByteArrayInputStream

  • 作用:从内存中的字节数组读取数据。
  • 使用范围:需要从字节数组模拟输入流的场景(如测试或数据处理)。
  • 示例代码
    byte[] data = "Hello, ByteArray!".getBytes();
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data)) {
        int byteValue;
        while ((byteValue = bais.read()) != -1) {
            System.out.print((char) byteValue);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

8. ByteArrayOutputStream

  • 作用:向内存中的字节数组写入数据。
  • 使用范围:需要将数据写入字节数组的场景(如动态生成内容)。
  • 示例代码
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        String text = "Hello, ByteArrayOutputStream!";
        baos.write(text.getBytes());
        byte[] result = baos.toByteArray(); // 获取字节数组
        System.out.println(new String(result));
    } catch (IOException e) {
        e.printStackTrace();
    }
    

9. DataInputStream

  • 作用:允许按基本数据类型(如 int, double)读取数据。
  • 使用范围:需要从流中读取结构化数据的场景。
  • 示例代码
    try (DataInputStream dis = new DataInputStream(
            new BufferedInputStream(
                new FileInputStream("data.bin")))) {
        int num = dis.readInt();
        double value = dis.readDouble();
        System.out.println("Read: " + num + ", " + value);
    } catch (IOException e) {
        e.printStackTrace();
    }
    

10. DataOutputStream

  • 作用:允许按基本数据类型写入数据。
  • 使用范围:需要向流中写入结构化数据的场景。
  • 示例代码
    try (DataOutputStream dos = new DataOutputStream(
            new BufferedOutputStream(
                new FileOutputStream("data.bin")))) {
        dos.writeInt(42);
        dos.writeDouble(3.1415);
        dos.flush(); // 确保数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

11. ObjectInputStream

  • 作用:从流中反序列化对象。
  • 使用范围:需要读取序列化对象的场景(如网络传输或文件存储)。
  • 示例代码
    try (ObjectInputStream ois = new ObjectInputStream(
            new FileInputStream("object.dat"))) {
        MyObject obj = (MyObject) ois.readObject();
        System.out.println(obj);
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    

12. ObjectOutputStream

  • 作用:将对象序列化到流中。
  • 使用范围:需要写入序列化对象的场景(如网络传输或文件存储)。
  • 示例代码
    try (ObjectOutputStream oos = new ObjectOutputStream(
            new FileOutputStream("object.dat"))) {
        MyObject obj = new MyObject("Test", 123);
        oos.writeObject(obj);
        oos.flush(); // 确保数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

补充说明

  • 资源管理:使用 try-with-resources 语法(如 try (InputStream is = ...))自动关闭流,避免资源泄漏。
  • 序列化要求:对象需实现 Serializable 接口才能被 ObjectInputStream/ObjectOutputStream 处理。
  • 性能优化:缓冲流(BufferedInputStream/BufferedOutputStream)通过减少 I/O 操作次数显著提升性能。以下是 Java 中常用输入输出流类的作用、使用范围及示例代码:

1. InputStream(抽象类)

  • 作用:所有字节输入流的超类,定义了从源读取字节的基本方法(如 read())。
  • 使用范围:作为其他字节输入流的基类,不直接实例化。
  • 示例代码
    // 通常通过子类使用,如 FileInputStream
    

2. OutputStream(抽象类)

  • 作用:所有字节输出流的超类,定义了向目标写入字节的基本方法(如 write())。
  • 使用范围:作为其他字节输出流的基类,不直接实例化。
  • 示例代码
    // 通常通过子类使用,如 FileOutputStream
    

3. FileInputStream

  • 作用:从文件系统读取字节数据。
  • 使用范围:需要读取本地文件内容的场景。
  • 示例代码
    try (FileInputStream fis = new FileInputStream("input.txt")) {
        int data;
        while ((data = fis.read()) != -1) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

4. FileOutputStream

  • 作用:向文件系统写入字节数据。
  • 使用范围:需要向本地文件写入内容的场景。
  • 示例代码
    try (FileOutputStream fos = new FileOutputStream("output.txt")) {
        String text = "Hello, World!";
        fos.write(text.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
    

5. BufferedInputStream

  • 作用:通过内部缓冲区提高字节输入流的读取性能。
  • 使用范围:需要高效读取大文件或频繁读取小数据块的场景。
  • 示例代码
    try (FileInputStream fis = new FileInputStream("input.txt");
         BufferedInputStream bis = new BufferedInputStream(fis)) {
        int data;
        while ((data = bis.read()) != -1) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

6. BufferedOutputStream

  • 作用:通过内部缓冲区提高字节输出流的写入性能。
  • 使用范围:需要高效写入大文件或频繁写入小数据块的场景。
  • 示例代码
    try (FileOutputStream fos = new FileOutputStream("output.txt");
         BufferedOutputStream bos = new BufferedOutputStream(fos)) {
        String text = "Hello, Buffered World!";
        bos.write(text.getBytes());
        bos.flush(); // 确保缓冲区数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

7. ByteArrayInputStream

  • 作用:从内存中的字节数组读取数据。
  • 使用范围:需要从字节数组模拟输入流的场景(如测试或数据处理)。
  • 示例代码
    byte[] data = "Hello, ByteArray!".getBytes();
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data)) {
        int byteValue;
        while ((byteValue = bais.read()) != -1) {
            System.out.print((char) byteValue);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

8. ByteArrayOutputStream

  • 作用:向内存中的字节数组写入数据。
  • 使用范围:需要将数据写入字节数组的场景(如动态生成内容)。
  • 示例代码
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        String text = "Hello, ByteArrayOutputStream!";
        baos.write(text.getBytes());
        byte[] result = baos.toByteArray(); // 获取字节数组
        System.out.println(new String(result));
    } catch (IOException e) {
        e.printStackTrace();
    }
    

9. DataInputStream

  • 作用:允许按基本数据类型(如 int, double)读取数据。
  • 使用范围:需要从流中读取结构化数据的场景。
  • 示例代码
    try (DataInputStream dis = new DataInputStream(
            new BufferedInputStream(
                new FileInputStream("data.bin")))) {
        int num = dis.readInt();
        double value = dis.readDouble();
        System.out.println("Read: " + num + ", " + value);
    } catch (IOException e) {
        e.printStackTrace();
    }
    

10. DataOutputStream

  • 作用:允许按基本数据类型写入数据。
  • 使用范围:需要向流中写入结构化数据的场景。
  • 示例代码
    try (DataOutputStream dos = new DataOutputStream(
            new BufferedOutputStream(
                new FileOutputStream("data.bin")))) {
        dos.writeInt(42);
        dos.writeDouble(3.1415);
        dos.flush(); // 确保数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

11. ObjectInputStream

  • 作用:从流中反序列化对象。
  • 使用范围:需要读取序列化对象的场景(如网络传输或文件存储)。
  • 示例代码
    try (ObjectInputStream ois = new ObjectInputStream(
            new FileInputStream("object.dat"))) {
        MyObject obj = (MyObject) ois.readObject();
        System.out.println(obj);
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    

12. ObjectOutputStream

  • 作用:将对象序列化到流中。
  • 使用范围:需要写入序列化对象的场景(如网络传输或文件存储)。
  • 示例代码
    try (ObjectOutputStream oos = new ObjectOutputStream(
            new FileOutputStream("object.dat"))) {
        MyObject obj = new MyObject("Test", 123);
        oos.writeObject(obj);
        oos.flush(); // 确保数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

补充说明

  • 资源管理:使用 try-with-resources 语法(如 try (InputStream is = ...))自动关闭流,避免资源泄漏。
  • 序列化要求:对象需实现 Serializable 接口才能被 ObjectInputStream/ObjectOutputStream 处理。
  • 性能优化:缓冲流(BufferedInputStream/BufferedOutputStream)通过减少 I/O 操作次数显著提升性能。

字符流

在Java中,字符流用于处理以字符为单位的数据输入和输出操作。与字节流不同,字符流专门处理文本数据,它们基于16位的Unicode字符集进行编码和解码,这使得字符流非常适合于读写文本文件或其他文本数据源。字符流的核心类位于java.io包中,主要包括抽象类Reader和Writer及其子类。

  • Reader:抽象类,所有字符输入流的超类。
  • Writer:抽象类,所有字符输出流的超类。
  • FileReaderFileWriter:分别用于从文件读取字符和向文件写入字符。
  • BufferedReaderBufferedWriter:通过内部缓冲区提高性能。
  • CharArrayReaderCharArrayWriter:在内存中以字符数组的形式存储数据。
  • InputStreamReaderOutputStreamWriter:桥接字节流和字符流,支持指定字符编码。
  • PrintWriter:提供格式化的打印功能。

1. Reader(抽象类)

  • 作用:所有字符输入流的超类,定义了从源读取字符的基本方法(如 read())。
  • 使用范围:作为其他字符输入流的基类,不直接实例化。
  • 示例代码
    // 通常通过子类使用,如 FileReader
    

2. Writer(抽象类)

  • 作用:所有字符输出流的超类,定义了向目标写入字符的基本方法(如 write())。
  • 使用范围:作为其他字符输出流的基类,不直接实例化。
  • 示例代码
    // 通常通过子类使用,如 FileWriter
    

3. FileReader

  • 作用:从文件系统读取字符数据。
  • 使用范围:需要读取本地文本文件的场景。
  • 示例代码
    try (FileReader fr = new FileReader("text.txt")) {
        int data;
        while ((data = fr.read()) != -1) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

4. FileWriter

  • 作用:向文件系统写入字符数据。
  • 使用范围:需要向本地文本文件写入内容的场景。
  • 示例代码
    try (FileWriter fw = new FileWriter("output.txt")) {
        String text = "Hello, FileWriter!";
        fw.write(text);
        fw.flush(); // 确保数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

5. BufferedReader

  • 作用:通过内部缓冲区提高字符输入流的读取性能。
  • 使用范围:需要高效读取大文本文件或频繁读取小数据块的场景。
  • 示例代码
    try (FileReader fr = new FileReader("text.txt");
         BufferedReader br = new BufferedReader(fr)) {
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

6. BufferedWriter

  • 作用:通过内部缓冲区提高字符输出流的写入性能。
  • 使用范围:需要高效写入大文本文件或频繁写入小数据块的场景。
  • 示例代码
    try (FileWriter fw = new FileWriter("output.txt");
         BufferedWriter bw = new BufferedWriter(fw)) {
        bw.write("Hello, BufferedWriter!");
        bw.newLine(); // 写入换行符
        bw.flush(); // 确保缓冲区数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

7. CharArrayReader

  • 作用:从内存中的字符数组读取数据。
  • 使用范围:需要从字符数组模拟输入流的场景(如测试或数据处理)。
  • 示例代码
    char[] data = "Hello, CharArray!".toCharArray();
    try (CharArrayReader car = new CharArrayReader(data)) {
        int charValue;
        while ((charValue = car.read()) != -1) {
            System.out.print((char) charValue);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

8. CharArrayWriter

  • 作用:向内存中的字符数组写入数据。
  • 使用范围:需要将数据写入字符数组的场景(如动态生成内容)。
  • 示例代码
    try (CharArrayWriter caw = new CharArrayWriter()) {
        String text = "Hello, CharArrayWriter!";
        caw.write(text);
        char[] result = caw.toCharArray(); // 获取字符数组
        System.out.println(new String(result));
    } catch (IOException e) {
        e.printStackTrace();
    }
    

9. InputStreamReader

  • 作用:将字节流转换为字符流,支持指定字符编码(如 UTF-8)。
  • 使用范围:需要按特定编码读取字节数据的场景(如网络传输或文件)。
  • 示例代码
    try (FileInputStream fis = new FileInputStream("text.bin");
         InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8)) {
        int data;
        while ((data = isr.read()) != -1) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

10. OutputStreamWriter

  • 作用:将字符流转换为字节流,支持指定字符编码(如 UTF-8)。
  • 使用范围:需要按特定编码写入字节数据的场景(如网络传输或文件)。
  • 示例代码
    try (FileOutputStream fos = new FileOutputStream("output.bin");
         OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
        String text = "Hello, OutputStreamWriter!";
        osw.write(text);
        osw.flush(); // 确保数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

11. PrintWriter

  • 作用:提供格式化的字符输出功能(如 printfprintln)。
  • 使用范围:需要向控制台或文件输出格式化文本的场景。
  • 示例代码
    try (PrintWriter pw = new PrintWriter(new FileWriter("output.txt"))) {
        pw.println("Hello, PrintWriter!");
        pw.printf("Number: %d, Pi: %.2f", 42, 3.1415);
        pw.flush(); // 确保数据写入文件
    } catch (IOException e) {
        e.printStackTrace();
    }
    

补充说明

  • 资源管理:使用 try-with-resources 语法自动关闭流,避免资源泄漏。
  • 字符编码:通过 InputStreamReader/OutputStreamWriter 指定编码(如 UTF-8),确保跨平台一致性。
  • 性能优化:缓冲流(BufferedReader/BufferedWriter)通过减少 I/O 操作次数显著提升性能。
  • 格式化输出PrintWriter 支持类似 System.out.printf 的格式化方法。

总结

  • 字节流:适合处理二进制数据。
  • 字符流:适合处理文本数据,自动处理字符编码和换行符。

网站公告

今日签到

点亮在社区的每一天
去签到