I/O流详解

        I/O(Input/Output)流是 Java 编程中用于处理输入和输出操作的一种机制。在计算机编程中,输入指的是从外部获取数据的过程,输出则是将数据发送到外部的过程。I/O 流提供了一种统一的方式来处理不同类型的数据输入和输出,无论是文件、网络连接、内存等,都可以通过 I/O 流进行读写操作。        

        I/O 流中常用的是字节流和字符流,它们用于处理不同类型的数据:字节流用于处理二进制数据,字符流用于处理文本数据。

字节流(Byte Stream):

特点:
  • 用于处理字节数据,适用于处理图像、音频、视频等二进制数据。
  • InputStream 和 OutputStream 是字节流的基类,提供了读取和写入字节数据的基本功能。
示例代码:
// 使用 FileInputStream 读取文件中的字节数据
try (FileInputStream fis = new FileInputStream("input.bin")) {
    int data;
    while ((data = fis.read()) != -1) {
        // 处理读取的字节数据
    }
} catch (IOException e) {
    e.printStackTrace();
}

// 使用 FileOutputStream 写入字节数据到文件
try (FileOutputStream fos = new FileOutputStream("output.bin")) {
    fos.write(new byte[]{0x48, 0x65, 0x6c, 0x6c, 0x6f}); // 写入 "Hello" 的 ASCII 码
} catch (IOException e) {
    e.printStackTrace();
}
使用环境:
  • 适用于处理二进制文件,如图像、音频、视频等。
  • 在网络编程中常用于传输二进制数据。

字符流(Character Stream):

特点:
  • 用于处理字符数据,适用于处理文本文件和字符串数据。
  • Reader 和 Writer 是字符流的基类,提供了读取和写入字符数据的基本功能。
示例代码:
// 使用 FileReader 读取文本文件中的字符数据
try (FileReader reader = new FileReader("input.txt")) {
    int data;
    while ((data = reader.read()) != -1) {
        // 处理读取的字符数据
    }
} catch (IOException e) {
    e.printStackTrace();
}

// 使用 FileWriter 写入字符数据到文本文件
try (FileWriter writer = new FileWriter("output.txt")) {
    writer.write("Hello, World!");
} catch (IOException e) {
    e.printStackTrace();
}
使用环境:
  • 适用于处理文本文件和字符串数据,能够正确处理字符编码。
  • 在处理文本文件时,字符流比字节流更方便和可靠。

总体来说,字节流适用于处理二进制数据,而字符流适用于处理文本数据。

缓冲流:缓冲字节流(BufferedInputStream 和 BufferedOutputStream)和缓冲字符流(BufferedReader 和 BufferedWriter)

        缓冲字节流(BufferedInputStream 和 BufferedOutputStream)和缓冲字符流(BufferedReader 和 BufferedWriter)是 Java 中用于提高 I/O 操作性能的工具。它们通过在内存中设置缓冲区来减少对底层资源的频繁访问,从而提高读写效率。接下来我将详细介绍缓冲字节流和缓冲字符流的特点、示例代码以及使用环境。

缓冲字节流(BufferedInputStream 和 BufferedOutputStream):

特点:
  • 提供了对底层 InputStream 和 OutputStream 进行缓冲的功能,减少对文件系统的频繁访问。
  • 使用缓冲区来一次性读取或写入一定量的数据,减少每次读写操作的系统调用次数。
示例代码:
// 使用 BufferedInputStream 读取文件中的字节数据
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.bin"))) {
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = bis.read(buffer)) != -1) {
        // 处理读取的字节数据
    }
} catch (IOException e) {
    e.printStackTrace();
}

// 使用 BufferedOutputStream 写入字节数据到文件
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.bin"))) {
    byte[] data = {0x48, 0x65, 0x6c, 0x6c, 0x6f};
    bos.write(data); // 写入 "Hello" 的 ASCII 码
} catch (IOException e) {
    e.printStackTrace();
}
使用环境:
  • 适用于处理大文件或需要频繁读写的情况。
  • 可以提高读写性能,特别是在网络编程或文件操作中。

缓冲字符流(BufferedReader 和 BufferedWriter):

特点:
  • 提供了对底层 Reader 和 Writer 进行缓冲的功能,减少对文件系统的频繁访问。
  • 使用缓冲区来一次性读取或写入一定量的字符数据,减少每次读写操作的系统调用次数。
示例代码:
// 使用 BufferedReader 读取文本文件中的字符数据
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        // 处理读取的一行字符数据
    }
} catch (IOException e) {
    e.printStackTrace();
}

// 使用 BufferedWriter 写入字符数据到文本文件
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
    writer.write("Hello, World!");
} catch (IOException e) {
    e.printStackTrace();
}
使用环境:
  • 适用于处理文本文件或字符串数据,避免出现乱码问题。
  • 可以提高读写性能,特别是在处理大量文本数据时。

        总体来说,缓冲流适用于需要提高 I/O 操作性能的场景,可以有效地减少对底层资源的访问次数,从而加快数据读写的速度。在选择使用缓冲流时,可以根据具体需求来确定使用缓冲字节流还是缓冲字符流,以达到最佳的性能优化效果。

对象流:ObjectInputStream 和 ObjectOutputStream

        对象流(ObjectInputStream和ObjectOutputStream)是Java中用于序列化和反序列化对象的流。对象序列化是将对象转换为字节流的过程,而对象反序列化是将字节流转换回对象的过程。对象流可以方便地将对象保存到文件、网络传输等场景中。

  • ObjectInputStream:用于从输入流中读取对象并进行反序列化。

  • ObjectOutputStream:用于将对象写入输出流并进行序列化。

示例代码:

下面是一个简单的示例代码,演示了如何使用对象流将对象序列化并写入文件,然后再从文件中读取并反序列化为对象:

import java.io.*;

// 定义一个可序列化的类
class Person implements Serializable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class ObjectStreamExample {
    public static void main(String[] args) {
        // 序列化对象到文件
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
            Person person = new Person("Alice", 30);
            oos.writeObject(person);
            System.out.println("Serialized: " + person);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 反序列化对象
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
            Person person = (Person) ois.readObject();
            System.out.println("Deserialized: " + person);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

        对象流是基于字节的流,即ObjectInputStreamObjectOutputStream。但是,如果想要基于字符进行对象的序列化和反序列化,也可以使用字符流结合对象流来实现。

示例代码:

下面是一个示例代码,演示了如何使用字符流结合对象流进行对象的序列化和反序列化:

 

java

import java.io.*;

// 定义一个可序列化的类
class Person implements Serializable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class ObjectCharStreamExample {
    public static void main(String[] args) {
        // 序列化对象到文件
        try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedWriter(new FileWriter("person.txt")))) {
            Person person = new Person("Alice", 30);
            oos.writeObject(person);
            System.out.println("Serialized: " + person);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 反序列化对象
        try (ObjectInputStream ois = new ObjectInputStream(new BufferedReader(new FileReader("person.txt")))) {
            Person person = (Person) ois.readObject();
            System.out.println("Deserialized: " + person);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

        在上面的示例中,我们通过字符流(BufferedWriterBufferedReader)将对象序列化到文本文件中,并从文本文件中反序列化对象。这样就实现了基于字符的对象序列化和反序列化。

        总之,虽然对象流是基于字节的,但是通过结合字符流,我们也可以实现基于字符的对象序列化和反序列化。这样可以更灵活地处理对象的序列化和反序列化需求。

使用环境:

对象流通常用于需要将对象序列化以便持久化存储或网络传输的场景。常见的使用环境包括:

  1. 文件存储:将对象序列化后保存到文件中,以便后续读取和恢复对象状态。
  2. 网络传输:在网络编程中,可以使用对象流将对象序列化后通过网络传输,并在接收端反序列化为对象。
  3. 缓存处理:在一些应用场景中,需要将对象缓存到磁盘或内存中,对象流可以帮助实现对象的序列化和反序列化。

总之,对象流提供了一种方便和高效的方式来处理对象的序列化和反序列化,使得对象在不同环境中的传输和存储更加灵活和便捷。

数据流:DataInputStream 和 DataOutputStream :

        数据流是 Java I/O 中的一种特殊类型,用于处理基本数据类型和对象的输入输出。数据流提供了更高级别的功能,可以直接读取和写入 Java 原始数据类型(如 int、double、boolean 等)以及对象,而无需进行数据的序列化和反序列化操作。

        Java 中常用的数据流包括 DataInputStream 和 DataOutputStream,它们分别用于从输入流中读取基本数据类型,以及将基本数据类型写入输出流。

  • 可以直接读写 Java 的基本数据类型和字符串数据,如 int、double、boolean、String 等。
  • 可以按照特定的顺序读写数据,无需考虑字节顺序或编解码问题。
  • 提供了方便的 API 方法来读写各种数据类型。

示例代码实现:

使用 DataOutputStream 写入数据到文件:
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"))) {
    dos.writeInt(42); // 写入整数
    dos.writeDouble(3.14); // 写入双精度浮点数
    dos.writeUTF("Hello, World!"); // 写入字符串
} catch (IOException e) {
    e.printStackTrace();
}
使用 DataInputStream 从文件中读取数据:
try (DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {
    int intValue = dis.readInt(); // 读取整数
    double doubleValue = dis.readDouble(); // 读取双精度浮点数
    String stringValue = dis.readUTF(); // 读取字符串
    System.out.println("Int: " + intValue + ", Double: " + doubleValue + ", String: " + stringValue);
} catch (IOException e) {
    e.printStackTrace();
}

使用环境:

  • 数据流适用于需要直接读写基本数据类型和字符串数据的场景,避免手动进行数据的转换和处理。
  • 可以在需要按照特定格式存储和读取数据的情况下使用,如配置文件、网络通信等。

        总的来说,数据流提供了一种方便快捷的方式来处理基本数据类型和字符串数据的读写操作,能够简化代码并提高操作的效率。在选择数据流时,需要根据具体的需求来决定是否使用,特别适合于处理基本数据类型和字符串数据的情况。

字符集流:InputStreamReader和OutputStreamWriter

        字符集流(Charset Stream)主要用于在字节流和字符流之间进行字符编码和解码的转换,以便处理不同字符集的文本数据。Java 提供了 InputStreamReader 和 OutputStreamWriter 作为字符集流的实现,它们可以将字节流转换为字符流,并指定特定的字符集编码方式。

  • InputStreamReader:
    • InputStreamReader 是用于将字节流转换为字符流的桥梁,它可以指定使用特定的字符集编码方式对字节数据进行解码。
    • 示例代码:
  • try (InputStream inputStream = new FileInputStream("input.txt");
         Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
        int data;
        while ((data = reader.read()) != -1) {
            // 处理读取的字符数据
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    在这个示例中,InputStreamReader 将文件输入流转换成字符输入流,并指定使用 UTF-8 字符集进行解码。

  • OutputStreamWriter:
    • OutputStreamWriter 是用于将字符流转换为字节流的桥梁,它可以指定使用特定的字符集编码方式对字符数据进行编码。
    • 示例代码:
  • try (OutputStream outputStream = new FileOutputStream("output.txt"); // 创建文件输出流
         Writer writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) { // 创建字符输出流,指定编码为UTF-8
        writer.write("Hello, this is a test."); // 写入数据到文件
    } catch (IOException e) { // 捕获IO异常
        e.printStackTrace(); // 打印异常信息
    }

    在这个示例中,OutputStreamWriter 将文件输出流转换成字符输出流,并指定使用 UTF-8 字符集进行编码。

使用环境:

        字符集流主要用于处理不同字符集编码的文本数据,在读写文件、网络通信等场景下非常常见。当需要明确指定字符集编码方式时,就可以使用字符集流来进行字符编码和解码的转换操作。例如,读取包含特定字符集编码的文本文件,或者将字符数据按照指定的字符集编码方式写入到文件或网络连接中。

        字符集流提供了在字节流和字符流之间进行字符编码和解码转换的功能,可以方便地处理不同字符集编码方式的文本数据。

打印流:PrintStream和PrintWriter

        打印流是Java I/O流的一种,用于方便地将数据输出到控制台或文件中。主要有PrintStream和PrintWriter两种类,它们提供了一系列的打印方法,可以将各种数据类型转换为字符串并输出。

  • PrintStream
    • PrintStream是字节打印流,继承自OutputStream。它提供了各种print和println方法,可以输出各种基本数据类型、对象等到目标输出流(如文件、控制台)。
    • 使用环境:适用于要向字节流输出文本数据的场景,常用于输出到文件或网络流中。

示例代码:

import java.io.*;

public class PrintStreamExample {
    public static void main(String[] args) {
        try {
            FileOutputStream fileOut = new FileOutputStream("output.txt"); // 创建文件输出流对象
            PrintStream printStream = new PrintStream(fileOut); // 创建PrintStream打印流对象

            printStream.println("Hello, PrintStream!"); // 使用println方法输出字符串
            printStream.printf("This is a number: %d\n", 123); // 使用printf方法格式化输出数字

            printStream.close(); // 关闭PrintStream流
        } catch (IOException e) { // 捕获IO异常
            e.printStackTrace(); // 打印异常信息
        }
    }
}
  • PrintWriter
    • PrintWriter是字符打印流,继承自Writer。与PrintStream类似,它也提供了各种print和println方法,用于输出各种数据类型到目标输出流。
    • 使用环境:适用于向字符流输出文本数据的场景,常用于输出到控制台或文本文件中。

示例代码:

import java.io.*;

public class PrintWriterExample {
    public static void main(String[] args) {
        try {
            FileWriter fileWriter = new FileWriter("output.txt"); // 创建文件字符输出流对象
            PrintWriter printWriter = new PrintWriter(fileWriter); // 创建PrintWriter打印流对象

            printWriter.println("Hello, PrintWriter!"); // 使用println方法输出字符串
            printWriter.printf("This is a number: %d\n", 456); // 使用printf方法格式化输出数字

            printWriter.close(); // 关闭PrintWriter流
        } catch (IOException e) { // 捕获IO异常
            e.printStackTrace(); // 打印异常信息
        }
    }
}

        这两个示例代码分别演示了使用PrintStream和PrintWriter将数据输出到文件中的过程。PrintStream适用于字节流,而PrintWriter适用于字符流。在实际应用中,根据需要选择合适的打印流类来输出数据。

不同流的区别:

  • 字节流:字节流以字节为单位进行读写,适用于处理二进制数据和非文本数据。
  • 字符流:字符流以字符为单位进行读写,提供了字符编码转换的功能,适用于处理文本数据。
  • 缓冲流:缓冲流是对输入输出流的包装,通过在内存中设立缓冲区来提高I/O性能。
  • 数据流:数据流可以按照Java基本数据类型进行读写操作,是字节流的一种扩展,提供了直接读写基本数据类型的方法。
  • 对象流:对象流是数据流的一种扩展,可以直接读写Java对象,实现了对象的序列化和反序列化。
  • 字符集流:字符集流提供了字符集编解码的功能,可以在字符流和字节流之间进行字符集转换。
  • 打印流:打印流提供了各种打印方法,方便将各种数据类型转换为字符串并输出到目标流中。

这些流在Java I/O中各自有不同的作用,根据具体需求选择合适的流来进行数据读写操作。

  • 34
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值