当前位置: 首页 > article >正文

Java IO 和 NIO 的基本概念和 API

一、 Java IO (Blocking IO)

  1. 基本概念:

    • Java IO 是 Java 平台提供的用于进行输入和输出操作的 API。
    • Java IO 基于 流 (Stream) 的模型,数据像水流一样从一个地方流向另一个地方。
    • Java IO 主要是 阻塞式 I/O (Blocking I/O),即线程在执行 I/O 操作时会被阻塞,直到操作完成。
    • 传统IO指的是java.io包下的部分组件(File, InputStream, OutputStream, Reader, Writer)。
  2. IO 流的分类:

    • 按数据传输方向:

      • 输入流 (Input Stream): 用于从数据源读取数据(例如,从文件、网络连接、键盘等)。 以 InputStreamReader 作为基类。
      • 输出流 (Output Stream): 用于将数据写入到目标(例如,写入到文件、网络连接、控制台等)。 以 OutputStreamWriter 作为基类。
    • 按数据传输单位:

      • 字节流 (Byte Stream): 以字节 (8 bits) 为单位进行数据传输。 以 InputStreamOutputStream 作为基类。 适用于处理二进制数据(例如,图片、音频、视频等)。
      • 字符流 (Character Stream): 以字符 (16 bits) 为单位进行数据传输。 以 ReaderWriter 作为基类。 适用于处理文本数据。
  3. 核心类和接口:

    • InputStream (字节输入流):

      • FileInputStream: 从文件中读取字节。
      • ByteArrayInputStream: 从字节数组中读取字节。
      • ObjectInputStream: 从对象流中读取对象。
      • BufferedInputStream: 带缓冲的字节输入流,提高读取效率。
    • OutputStream (字节输出流):

      • FileOutputStream: 向文件中写入字节。
      • ByteArrayOutputStream: 向字节数组中写入字节。
      • ObjectOutputStream: 向对象流中写入对象。
      • BufferedOutputStream: 带缓冲的字节输出流,提高写入效率。
    • Reader (字符输入流):

      • FileReader: 从文件中读取字符。
      • CharArrayReader: 从字符数组中读取字符。
      • BufferedReader: 带缓冲的字符输入流,提高读取效率。
      • InputStreamReader: 将字节输入流转换为字符输入流(需要指定字符编码)。
    • Writer (字符输出流):

      • FileWriter: 向文件中写入字符。
      • CharArrayWriter: 向字符数组中写入字符。
      • BufferedWriter: 带缓冲的字符输出流,提高写入效率。
      • OutputStreamWriter: 将字节输出流转换为字符输出流(需要指定字符编码)。
    • File: 表示文件或目录的抽象表示。

  4. IO 操作流程 (以读取文件为例):

    1. 创建 File 对象: 指定要读取的文件路径。
    2. 创建 FileInputStream 对象:File 对象作为参数传递给 FileInputStream 的构造方法,创建一个 FileInputStream 对象。
    3. 创建 BufferedInputStream 对象 (可选):FileInputStream 对象作为参数传递给 BufferedInputStream 的构造方法,创建一个 BufferedInputStream 对象,提高读取效率。
    4. 读取数据: 使用 read() 方法从输入流中读取数据。
    5. 关闭流: 在完成读取操作后,务必关闭输入流,释放资源(先关闭 BufferedInputStream,再关闭 FileInputStream)。
  5. 代码示例 (读取文件内容):

    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;public class IOExample {public static void main(String[] args) {File file = new File("test.txt"); // 替换为你的文件路径try (FileInputStream fis = new FileInputStream(file);BufferedInputStream bis = new BufferedInputStream(fis)) { // 使用 try-with-resources 语句,自动关闭流byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = bis.read(buffer)) != -1) {// 处理读取到的数据String data = new String(buffer, 0, bytesRead);System.out.print(data);}} catch (IOException e) {e.printStackTrace();}}
    }
    

二、 Java NIO (Non-blocking IO)

  1. 基本概念:

    • Java NIO 是 Java 1.4 引入的一组新的 I/O API,旨在提供高性能、非阻塞的 I/O 操作。
    • NIO 使用 通道 (Channel)缓冲区 (Buffer) 的模型,而不是流。
    • NIO 主要是 非阻塞式 I/O (Non-blocking I/O),即线程在执行 I/O 操作时不会被阻塞,而是可以执行其他任务。
    • NIO 使用 选择器 (Selector) 来监听多个通道的事件,实现单线程管理多个连接。
  2. 核心组件:

    • 通道 (Channel):

      • 通道类似于流,但可以进行双向数据传输(既可以读取数据,也可以写入数据)。
      • 常见的通道:
        • FileChannel: 用于文件 I/O。
        • SocketChannel: 用于 TCP 网络 I/O (客户端)。
        • ServerSocketChannel: 用于 TCP 网络 I/O (服务器端)。
        • DatagramChannel: 用于 UDP 网络 I/O。
    • 缓冲区 (Buffer):

      • 缓冲区是用于存储数据的容器,本质上是一个字节数组 (ByteBuffer) 或字符数组 (CharBuffer)。
      • NIO 使用缓冲区进行数据传输,而不是直接从通道读取数据或向通道写入数据。
      • 常见的缓冲区:
        • ByteBuffer: 字节缓冲区。
        • CharBuffer: 字符缓冲区。
        • ShortBuffer: 短整型缓冲区。
        • IntBuffer: 整型缓冲区。
        • LongBuffer: 长整型缓冲区。
        • FloatBuffer: 浮点型缓冲区。
        • DoubleBuffer: 双精度浮点型缓冲区。
    • 选择器 (Selector):

      • 选择器允许单个线程监听多个通道的事件(例如连接建立、数据可读、数据可写等)。
      • 使用选择器可以避免为每个连接创建一个线程,从而提高并发性能。
  3. NIO 操作流程 (以读取 SocketChannel 数据为例):

    1. 创建 ServerSocketChannel 监听客户端连接。
    2. 创建 SocketChannel 接受客户端连接。
    3. SocketChannel 注册到 Selector 指定要监听的事件(例如 OP_READ, OP_WRITE, OP_CONNECT, OP_ACCEPT)。
    4. 创建 ByteBuffer 用于存储读取到的数据。
    5. 调用 selector.select() 方法: 阻塞等待有事件发生的通道。
    6. 获取就绪的通道: selector.selectedKeys() 返回所有就绪通道的集合。
    7. 处理事件: 遍历就绪通道的集合,根据不同的事件类型执行相应的操作(例如读取数据、写入数据)。
    8. 读取数据: 调用 channel.read(buffer) 从通道读取数据到缓冲区。
    9. 处理缓冲区数据: 从缓冲区读取数据并进行处理。
    10. 关闭通道和选择器: 在完成操作后,务必关闭通道和选择器,释放资源。
  4. 代码示例 (使用 SocketChannel 读取数据):

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;public class NIOExample {public static void main(String[] args) throws IOException {// 1. 创建 SocketChannelSocketChannel socketChannel = SocketChannel.open();socketChannel.connect(new InetSocketAddress("www.example.com", 80));socketChannel.configureBlocking(false); // 设置为非阻塞模式// 2. 创建 ByteBufferByteBuffer buffer = ByteBuffer.allocate(1024);// 3. 从 Channel 读取数据到 Bufferint bytesRead = socketChannel.read(buffer);while (bytesRead > 0) {// 切换到读模式buffer.flip();// 4. 从 Buffer 读取数据while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}// 清空 Buffer,准备下一次读取buffer.clear();bytesRead = socketChannel.read(buffer);}socketChannel.close();}
    }
    

三、 Java IO 与 NIO 的区别

特性Java IO (Blocking IO)Java NIO (Non-blocking IO)
数据传输方式基于流 (Stream)基于通道 (Channel) 和缓冲区 (Buffer)
I/O 模型阻塞式 I/O (Blocking I/O)非阻塞式 I/O (Non-blocking I/O)
选择器没有有 (Selector)
API简单易用相对复杂,需要理解通道、缓冲区、选择器等概念
性能性能较低 (高并发下)性能较高 (高并发下)
线程模型通常使用多线程模型 (每个连接一个线程)通常使用单线程多路复用模型 (一个线程管理多个连接)
适用场景低并发、连接数较少的应用,或者可以接受阻塞的场景高并发、连接数较多的应用,需要高性能和非阻塞的场景,例如网络服务器、聊天服务器等

四、 选择哪种 I/O 模式?

  • 如果你的应用是低并发、连接数较少,并且可以接受阻塞,那么 Java IO 仍然是一个不错的选择,因为它简单易用。
  • 如果你的应用是高并发、连接数较多,并且对性能要求很高,那么应该使用 Java NIO。
  • 一般情况建议直接使用NIO模型,性能更好。

总结

Java IO 和 NIO 都是 Java 平台提供的用于进行输入和输出操作的 API。 Java IO 基于流的模型,使用简单但性能较低; Java NIO 基于通道和缓冲区的模型,提供高性能、非阻塞的 I/O 操作。

相关文章:

Java IO 和 NIO 的基本概念和 API

一、 Java IO (Blocking IO) 基本概念: Java IO 是 Java 平台提供的用于进行输入和输出操作的 API。Java IO 基于 流 (Stream) 的模型,数据像水流一样从一个地方流向另一个地方。Java IO 主要是 阻塞式 I/O (Blocking I/O),即线程在执行 I/O …...

【数据结构】快指针和慢指针

一、 给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。 要求:只遍历一遍链表 可以使用快慢指针:fast 一次走两步,slow 一次走一步。当 fast NULL(偶数个结点)或…...

四、综合案例(Unity2D)

一、2D渲染 1、2D相机基本设置 上面是透视,下面是正交 2、图片资源 在Unity中,常规图片导入之后,一般不在Unity中直接使用,而是转为精灵图Sprite 将图片更改为即可使用Unity内置的图片切割功能 无论精灵图片是单个的还是多个的…...

全面汇总windows进程通信(三)

在Windows操作系统下,实现进程间通信(IPC, Inter-Process Communication)有几种常见的方法,包括使用管道(Pipe)、共享内存(Shared Memory)、消息队列(Message Queue)、命名管道(Named Pipe)、套接字(Socket)等。本文介绍如下几种: RPC(远程过程调用,Remote Pr…...

Caffeine:高性能的Java本地缓存库

文章目录 引言什么是Caffeine?Caffeine的主要特点Caffeine的使用方法Caffeine与Google Guava Cache的对比Caffeine与Ehcache的对比总结 引言 在现代软件开发中,缓存是提高应用性能的重要手段之一。通过缓存,可以减少对数据库或其他外部系统的…...

Codes 开源免费研发项目管理平台 2025年第一个大版本3.0.0 版本发布及创新的轻IPD实现

Codes 简介 Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台,支持云端认证、本地部署、全部功能开放,并且对 30 人以下团队免费。它通过创新的方式简化研发协同工作,使敏捷开发更易于实施。并提供低成本的敏捷开发解决方案&#xff0…...

flowable 全生命周期涉及到的api及mysql表

要了解Flowable从流程创建到审批过程中涉及的API和MySQL表。之前对工作流引擎有一些基础了解,但具体到Flowable的细节可能不太熟悉。需要先回忆一下Flowable的基本概念,比如流程定义、流程实例、任务、执行实例等,然后逐步思考每个步骤会用到…...

Golang | 每日一练 (3)

💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Golang | 每日一练 (3)题目参考答案map 实现原理hmapb…...

【java】类声明的两种形式

在 Java 中,类的声明有两种形式: public class Test class Test 它们的区别主要在于访问权限和文件名的要求。下面我会详细解释这两种形式的区别。 1. public class Test 访问权限: public 表示这个类是公共的,可以被其他包&am…...

VSCode 中设置 Git 忽略仅因时间戳修改导致的文件变更【使用deepseek生成的一篇文章】

在 VSCode 中设置 Git 忽略仅因时间戳修改导致的文件变更&#xff0c;可通过以下步骤实现&#xff1a; 确认是否为纯时间戳修改 首先确认文件的修改是否仅涉及时间戳&#xff0c;使用终端运行&#xff1a; git diff -- <file>若输出为空但 Git 仍提示修改&#xff0c;可…...

Docker入门及基本概念

让我们从最基础的概念开始逐步理解。假设你已经准备好了docker 环境。 第一步&#xff0c;让我们先通过实际操作来看看当前系统中的镜像(images)和容器(containers)状态&#xff1a; docker images # 查看所有镜像 docker ps -a # 查看所有容器&#xff08;包括未运行…...

java八股文-消息队列

一、MQ基础篇 1. 什么是消息队列&#xff1f; 消息队列&#xff08;MQ&#xff09;是分布式系统中实现异步通信的中间件&#xff0c;解耦生产者和消费者。 2. 使用场景有哪些&#xff1f; 异步处理&#xff08;如注册后发送邮件&#xff09;系统解耦&#xff08;不同服务通过…...

设备唯一ID获取,支持安卓/iOS/鸿蒙Next(uni-device-id)UTS插件

设备唯一ID获取 支持安卓/iOS/鸿蒙(uni-device-id)UTS插件 介绍 获取设备唯一ID、设备唯一标识&#xff0c;支持安卓&#xff08;AndroidId/OAID/IMEI/MEID/MacAddress/Serial/UUID/设备基础信息&#xff09;,iOS&#xff08;Identifier/UUID&#xff09;&#xff0c;鸿蒙&am…...

基于Springboot医院预约挂号小程序系统【附源码】

基于Springboot医院预约挂号小程序系统 效果如下&#xff1a; 小程序主页面 帖子页面 医生账号页面 留言内容页面 管理员主页面 用户管理页面 我的挂号页面 医生管理页面 研究背景 随着信息技术的飞速发展和互联网医疗的兴起&#xff0c;传统的医疗服务模式正面临着深刻的变…...

微信小程序 - 页面跳转(wx.navigateTo、wx.redirectTo、wx.switchTab、wx.reLaunch)

API 跳转 1、wx.navigateTo &#xff08;1&#xff09;基本介绍 功能&#xff1a;保留当前页面&#xff0c;跳转到应用内的某个页面&#xff0c;使用该方法跳转后可以通过返回按钮返回到原页面 使用场景&#xff1a;适用于需要保留当前页面状态&#xff0c;后续还需返回的情…...

如何手动设置u-boot的以太网的IP地址、子网掩码、网关信息、TFTP的服务器地址,并进行测试

设置IP地址 运行下面这条命令设置u-boot的以太网的IP地址&#xff1a; setenv ipaddr 192.168.5.9设置子网掩码 运行下面这条命令设置u-boot的以太网的子网掩码&#xff1a; setenv netmask 255.255.255.0设置网关信息 运行下面这条命令设置u-boot的网关信息&#xff1a; …...

小红书运营教程(内容笔记01)

# 小红书笔记引流实战指南:合规涨粉与精准引流策略## 一、引流底层逻辑:平台算法与用户心理### 1.1 小红书流量推荐机制 ```mermaid graph TD A[笔记发布] --> B(机器初审) B --> C{内容质量检测} C -->|通过| D[进入初级流量池200-500曝光] D --> E{互动率达标?…...

tortoiseGit的使用和上传拉取

tortoiseGit的使用和上传拉取 下载TortoiseGit 通过网盘分享的文件&#xff1a;tortoiseGit.zip 链接: https://pan.baidu.com/s/1EOT_UsM9_OysRqXa8gES4A?pwd1234 提取码: 1234 在电脑桌面新建文件夹并进入 右击鼠标 将网址复制上去 用户名和密码是在git注册的用户名和…...

IDEA通过Maven使用JBLJavaToWeb插件创建Web项目

第一步&#xff1a;IDEA下载JBLJavaToWeb插件 File--->Settings--->Plugins--->Marketplace搜索: JBLJavaToWeb 第二步&#xff1a;创建普通Maven工程 第三步&#xff1a; 将普通Maven项目转换为Web项目...

【新手初学】SQL注入之二次注入、中转注入

二次注入 一、概念 二次注入可以理解为&#xff0c;攻击者构造的恶意数据存储在数据库后&#xff0c;恶意数据被读取并进入到SQL查询语句所导致的注入。 二、原理 防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理&#xff0c;但在恶意数据插入到数据库时被处…...

【第四节】C++设计模式(创建型模式)-Builder(建造者)模式

目录 引言 一、Builder 模式概述 二、Builder 模式举例 三、Builder 模式的结构 四、Builder 模式的实现 五、Builder 模式的优缺点 六、总结 引言 Builder 模式是一种创建型设计模式&#xff0c;旨在将复杂对象的构建过程与其表示分离。通过一步步构建对象&#xff0c;…...

本地部署AI模型 --- DeepSeek(二)---更新中

目录 FAQ 1.Failed to load the model Exit code: 18446744072635812000 FAQ 1.Failed to load the model Exit code: 18446744072635812000 问题描述&#xff1a; &#x1f972; Failed to load the model Error loading model. (Exit code: 18446744072635812000). Unkn…...

MariaDB 历史版本下载地址 —— 筑梦之路

MariaDB 官方yum源里面只有目前在维护的版本&#xff0c;而有时候对于老项目来说还是需要老版本的rpm包&#xff0c;国内很多镜像站都是同步的官方仓库&#xff0c;因此下载老版本也不好找&#xff0c;这里主要记录下从哪里可以下载到历史版本的MariaDB rpm包。 1. 官方归档网…...

Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件

一.类的介绍 1.QPdfWriter介绍 Qt中提供了一个直接可以处理PDF的类&#xff0c;这就是QPdfWriter类。 &#xff08;1&#xff09;PDF文件生成 支持创建新的PDF文件或覆盖已有文件&#xff0c;通过构造函数直接绑定文件路径或QFile对象&#xff1b; 默认生成矢量图形PDF&#…...

使用 Promptic 进行对话管理需要具备python技术中的那些编程能力?

使用 Promptic 进行对话管理时,需要掌握一些基础的编程知识和技能,以下是详细说明: 1. Python 编程基础 Promptic 是一个基于 Python 的开发框架,因此需要具备一定的 Python 编程能力,包括: 函数定义与使用:了解如何定义函数、使用参数和返回值。类型注解:熟悉 Python…...

使用 DeepSeek 生成流程图、甘特图与思维导图:结合 Typora 和 XMind 的高效工作流

在现代工作与学习中&#xff0c;可视化工具如流程图、甘特图和思维导图能够极大地提升信息整理与表达的效率。本文将详细介绍如何使用 DeepSeek 生成 Mermaid 文本&#xff0c;结合 Typora 快速生成流程图和甘特图&#xff0c;并通过 Markdown 格式生成思维导图&#xff0c;最终…...

遗传算法初探

组成要素 编码 分为二进制编码、实数编码和顺序编码 初始种群的产生 分为随机方法、基于反向学习优化的种群产生。 基于反向学习优化的种群其思想是先随机生成一个种群P(N)&#xff0c;然后按照反向学习方法生成新的种群OP(N),合并两个种群&#xff0c;得到一个新的种群S(N…...

Oracle 连接报错:“ORA-12541:TNS:no listener ”,服务组件中找不到监听服务

一、 报错&#xff1a; navicat连接数据库报错&#xff1a;ORA-12541&#xff1a;TNS:no listener 二、排查问题 三、 解决问题 删除Oracle安装目录下选中的配置&#xff1a;listener.ora 及 listener*.bak相关的 cmd&#xff0c;用管理员打开 执行&#xff1a;netca 命…...

一文详解U盘启动UEFI/Legacy方式以及GPT/MBR关系

对于装系统的老手而说一直想研究一下装系统的原理&#xff0c;以及面对一些问题时的解决思路&#xff0c;故对以前的方法进行原理上的解释&#xff0c;主要想理解其底层原理。 引导模式 MBR分区可以同时支持UEFI和Legacy引导&#xff0c;我们可以看一下微pe制作的启动盘&#…...

计算机毕设-基于springboot的汽车配件销售管理系统的设计与实现(附源码+lw+ppt+开题报告)

博主介绍&#xff1a;✌多个项目实战经验、多个大型网购商城开发经验、在某机构指导学员上千名、专注于本行业领域✌ 技术范围&#xff1a;Java实战项目、Python实战项目、微信小程序/安卓实战项目、爬虫大数据实战项目、Nodejs实战项目、PHP实战项目、.NET实战项目、Golang实战…...