Java输入流与输出流超全面讲解

 更新时间:2025年05月07日 09:26:46   作者:eason再来一次  
这篇文章主要介绍了关于Java输入流与输出流的相关资料,包括它们的定义、作用、最基础的类和方法,以及如何以其他单位进行读取,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、输入流与输出流的定义及作用

定义

  • 输入流(Input Stream):在 Java 世界里,输入流是一种机制,它负责从外部世界(像硬盘文件系统、网络连接、内存数组等数据源)读取数据到程序内部。

  • 输出流(Output Stream):输出流则是将程序里的数据输出到外部世界,外部世界可以是文件、网络连接等目标位置。

作用

输入流和输出流是 Java 实现数据输入输出操作的核心,它们搭建起了程序与外部环境之间的数据交互桥梁,使得程序能够读取外部数据进行处理,也能将处理结果输出到外部。

比如说把控制台的数据读入到程序当中。或者说把程序当中的数据输出到控制台

import java.io.IOException;

public class ReadByteByByte {
    public static void main(String[] args) {
        try {
            System.out.println("请输入一些内容:");
            int input;
            while ((input = System.in.read()) != -1) {
                System.out.print((char) input);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二、输入流和输出流最基础的类及方法使用

基础类

Java 中,InputStream 和 OutputStream 分别是输入流和输出流的最基础抽象类。它们以字节作为读取和写入数据的基本单元。

常用方法及使用示例

InputStream 类

  • int read():该方法从输入流中读取一个字节的数据,返回值是该字节对应的整数(范围为 0 - 255)。当到达流的末尾时,返回 -1。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamExample {
    public static void main(String[] args) {
        try (InputStream is = new FileInputStream("input.txt")) {
            int byteData;
            while ((byteData = is.read()) != -1) {
                System.out.print((char) byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • int read(byte[] b):尝试将最多 b.length 个字节的数据读入到字节数组 b 中,返回实际读取的字节数。若到达流末尾,返回 -1。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamReadArrayExample {
    public static void main(String[] args) {
        try (InputStream is = new FileInputStream("input.txt")) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                for (int i = 0; i < bytesRead; i++) {
                    System.out.print((char) buffer[i]);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

OutputStream 类

  • void write(int b):将指定的字节写入输出流。这里的参数 b 虽然是 int 类型,但实际上只使用低 8 位。

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    
    public class OutputStreamExample {
        public static void main(String[] args) {
            try (OutputStream os = new FileOutputStream("output.txt")) {
                String data = "Hello, World!";
                for (int i = 0; i < data.length(); i++) {
                    os.write(data.charAt(i));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • void write(byte[] b):将字节数组 b 中的所有字节写入输出流。

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamWriteArrayExample {
    public static void main(String[] args) {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            String data = "Hello, Java!";
            byte[] buffer = data.getBytes();
            os.write(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

三、能否以其他单位进行读取

虽然 InputStream 和 OutputStream 以字节为基础单位进行读取和写入,但 Java 也提供了以其他单位进行操作的方式:

字符

可以使用字符流来以字符为单位进行读取和写入。字符流基于字节流构建,会自动处理字符的编码和解码。例如 Reader 和 Writer 是字符流的抽象基类,FileReader 和 FileWriter 是具体实现类。

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

public class CharacterStreamExample {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("input.txt");
             FileWriter fw = new FileWriter("output.txt")) {
            int charData;
            while ((charData = fr.read()) != -1) {
                fw.write(charData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

数字和对象

对于数字和对象,可以使用数据流和对象流。

  • 数据流:DataInputStream 和 DataOutputStream 可以方便地读写基本数据类型(如 intdouble 等)。

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataStreamExample {
    public static void main(String[] args) {
        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"));
             DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {
            dos.writeInt(123);
            int num = dis.readInt();
            System.out.println(num);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 对象流:ObjectInputStream 和 ObjectOutputStream 用于读写 Java 对象。对象需要实现 Serializable 接口才能进行序列化和反序列化。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Person implements Serializable {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class ObjectStreamExample {
    public static void main(String[] args) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"));
             ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
            Person person = new Person("John", 30);
            oos.writeObject(person);
            Person readPerson = (Person) ois.readObject();
            System.out.println("Name: " + readPerson.getName() + ", Age: " + readPerson.getAge());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

四、字符流、对象流等与字节流的关系

字符流、对象流、数据流等都与字节流密切相关,它们是在字节流的基础上构建起来的。

  • 字符流:在字节流的基础上添加了字符编码协议。在读取数据时,根据编码协议读取指定数量的字节,然后进行解码得到对应的字符;在写入数据时,将字符编码为字节后通过字节流输出。

  • 对象流:输入时先获取对象的序列化结果(字节流),然后使用字节流读取,再进行反序列化得到对象;输出时将对象进行序列化得到字节流,然后使用字节流将字节流传输出去。

  • 数据流:同样是在字节流的基础上,提供了读写基本数据类型的功能,会将基本数据类型转换为字节进行读写。

综上所述,字节流是 Java 输入输出流体系的基础,其他类型的流都是为了满足不同的数据处理需求而在字节流基础上进行的扩展。

五、Buffered 输入流实现更快读取效率的原理

我看FIleInputStream每次读数据都要调用本地方法read0,如果碰到大文件频繁调用,可能导致效率会比较低,有什么更好的方法吗?

在 Java 中,像 BufferedInputStream 和 BufferedReader 这类带有缓冲区(Buffer)的输入流能够提升读取效率,其核心原理在于减少系统调用的次数。以下是具体的解释:

  • 系统调用开销

系统调用是指程序向操作系统内核请求服务的过程,例如从磁盘、网络或控制台读取数据。每次进行系统调用都需要进行上下文切换,也就是从用户态切换到内核态,这个过程会消耗大量的时间和资源。如果每次只读取少量的数据,就会频繁地进行系统调用,从而导致效率低下。

  • 缓冲区的作用

带有缓冲区的输入流在内部维护了一个缓冲区(通常是一个字节数组或字符数组)。当程序第一次调用读取方法时,它会进行一次系统调用,从数据源(如文件、网络等)中读取一大块数据到缓冲区中。之后,程序再进行读取操作时,会先从缓冲区中获取数据,而不是直接进行系统调用。只有当缓冲区中的数据被读完后,才会再次进行系统调用,读取新的数据到缓冲区。

例如,BufferedInputStream 会一次性从底层输入流(如 FileInputStream)中读取多个字节到其内部的字节数组缓冲区,后续的读取操作就可以直接从这个缓冲区获取数据,减少了与底层输入源的交互次数,从而提高了读取效率。

Buffered 输入流的使用方法

1. BufferedInputStream 的使用(处理字节流)

BufferedInputStream 用于处理字节流,以下是一个简单的示例,展示如何使用 BufferedInputStream 读取文件:

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class BufferedInputStreamExample {
    public static void main(String[] args) {
        try (InputStream fis = new FileInputStream("example.txt");
             BufferedInputStream bis = new BufferedInputStream(fis)) {
            int byteData;
            while ((byteData = bis.read()) != -1) {
                System.out.print((char) byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,首先创建了一个 FileInputStream 用于从文件中读取字节数据,然后将其作为参数传递给 BufferedInputStream 的构造函数,创建一个带有缓冲区的输入流。之后,通过 BufferedInputStream 的 read() 方法读取数据,它会先从缓冲区中获取数据,当缓冲区为空时再进行系统调用读取新的数据。

2. BufferedReader 的使用(处理字符流)

BufferedReader 用于处理字符流,以下是一个使用 BufferedReader 读取文件的示例:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,创建了一个 FileReader 用于从文件中读取字符数据,然后将其传递给 BufferedReader 的构造函数。BufferedReader 会将字符数据读取到其内部的缓冲区,通过 readLine() 方法可以方便地按行读取数据,提高了读取文本文件的效率。

通过使用带有缓冲区的输入流,可以显著减少系统调用的次数,从而提高数据读取的效率。

总结

到此这篇关于Java输入流与输出流的文章就介绍到这了,更多相关Java输入流与输出流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot一个接口多个实现类的调用方式总结

    SpringBoot一个接口多个实现类的调用方式总结

    这篇文章主要介绍了SpringBoot一个接口多个实现类的调用方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01
  • Spring配置类源码分析详解

    Spring配置类源码分析详解

    这篇文章主要介绍了Spring配置类解析源码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-09-09
  • Java中json格式化BigDecimal保留2位小数

    Java中json格式化BigDecimal保留2位小数

    这篇文章主要给大家介绍了关于Java中json格式化BigDecimal保留2位小数的相关资料,BigDecimal是Java中的一个数学库,可以实现高精度计算,文中给出了详细的代码实例,需要的朋友可以参考下
    2023-09-09
  • maven项目pom.xml中parent标签的使用小结

    maven项目pom.xml中parent标签的使用小结

    使用maven是为了更好的帮项目管理包依赖,maven的核心就是pom.xml,当我们需要引入一个jar包时,在pom文件中加上就可以从仓库中依赖到相应的jar包,本文就来介绍一下maven项目pom.xml中parent标签的使用小结,感兴趣的可以了解一下
    2023-12-12
  • java中的反射及其优点说明

    java中的反射及其优点说明

    这篇文章主要介绍了java中的反射及其优点说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • Java Chassis3应用视角的配置管理技术解密

    Java Chassis3应用视角的配置管理技术解密

    这篇文章主要为大家介绍了Java Chassis3应用视角的配置管理相关的机制和背后故事,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • SpringMVC+ZTree实现树形菜单权限配置的方法

    SpringMVC+ZTree实现树形菜单权限配置的方法

    本篇文章主要介绍了SpringMVC+ZTree实现树形菜单权限配置的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • SpringBoot整合多个Mq服务做法详解

    SpringBoot整合多个Mq服务做法详解

    SpringBoot整合rabbitmq很容易,但是整合的目的是为了使用,那要使用rabbitmq就要对其有一定的了解,不然容易整成一团浆糊。因为说到底,SpringBoot只是在封装rabbitmq的API,让其更容易使用而已,废话不多说,让我们一起整它
    2023-02-02
  • Spring源码之事件监听机制详解(@EventListener实现方式)

    Spring源码之事件监听机制详解(@EventListener实现方式)

    这篇文章主要介绍了Spring源码之事件监听机制(@EventListener实现方式),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • idea2020.3.3集成maven及遇到的坑(推荐)

    idea2020.3.3集成maven及遇到的坑(推荐)

    这篇文章主要介绍了idea2020.3.3集成maven的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03

最新评论