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

输入输出(I/O):熟悉 Java 的 I/O 类库,尤其是 NIO 和文件操作

输入输出(I/O):熟悉 Java 的 I/O 类库,尤其是 NIO 和文件操作

在 Java 中,I/O(输入输出)操作是开发中非常重要的一部分,用于与文件、网络和其他数据流交互。Java 提供了传统的 I/O(基于流的 I/O)和更现代的 NIO(非阻塞 I/O)两种方式。本文将带你熟悉 Java I/O 的核心类库,并重点介绍 NIO 的特点及文件操作相关内容。


一、Java I/O 的基本概念

  • 1.1 流(Stream)

    流(Stream)是 Java I/O 的核心概念,代表了数据传输的路径。在 Java 中,流的概念被分为 输入流输出流,并且每种流都可以分为字节流和字符流。

    • 输入流(Input Stream): 从数据源读取数据。
    • 输出流(Output Stream): 向目标写入数据。
    字节流与字符流
    • 字节流(Byte Stream): 以字节为单位进行数据读写。适用于所有类型的I/O操作,包括文本、图像、音频等。
      • InputStreamOutputStream 是字节流的根类。
      • 常用类:FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream
    • 字符流(Character Stream): 以字符为单位进行数据读写,适用于文本文件的处理。
      • ReaderWriter 是字符流的根类。
      • 常用类:FileReader, FileWriter, BufferedReader, BufferedWriter
    示例代码:字节流和字符流的使用
    // 使用字节流读取文件
    import java.io.*;public class ByteStreamExample {public static void main(String[] args) throws IOException {FileInputStream inputStream = new FileInputStream("example.txt");int byteData;while ((byteData = inputStream.read()) != -1) {System.out.print((char) byteData); // 输出文件内容}inputStream.close();}
    }// 使用字符流读取文件
    import java.io.*;public class CharStreamExample {public static void main(String[] args) throws IOException {FileReader fileReader = new FileReader("example.txt");BufferedReader bufferedReader = new BufferedReader(fileReader);String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line); // 输出文件内容}bufferedReader.close();}
    }
    

二、常见的 Java I/O 类库

2.1 文件操作类

  1. File 类:

    是 Java 早期提供的文件操作类,提供了创建、删除文件和目录的功能。

    • 优点:操作简单。
    • 缺点:功能有限,不支持高级操作如复制、移动等。
示例代码:
import java.io.File;public class FileExample {public static void main(String[] args) {File file = new File("example.txt");// 创建文件try {if (file.createNewFile()) {System.out.println("File created: " + file.getName());} else {System.out.println("File already exists.");}} catch (Exception e) {e.printStackTrace();}// 删除文件if (file.delete()) {System.out.println("Deleted the file: " + file.getName());}}
}
  1. Files 类:

    Java 7 引入的 NIO 类,提供了文件操作的高级接口,支持复制、移动、删除等操作。

    • 优点:功能丰富,支持文件复制、移动、文件权限操作等。
    • 常用方法:copy(), move(), delete(), exists(), createDirectory() 等。
示例代码:使用 Files 类进行文件复制
import java.nio.file.*;public class FilesExample {public static void main(String[] args) {Path source = Paths.get("source.txt");Path target = Paths.get("target.txt");try {Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);System.out.println("File copied successfully.");} catch (Exception e) {e.printStackTrace();}}
}

三、Java NIO 的特点与使用

3.1 什么是 NIO?

NIO(New I/O)是 Java 1.4 引入的一组 API,旨在提供比传统 I/O 更高效的操作。它支持基于缓冲区和通道的 I/O 方式,能有效提高性能。

  • 传统 I/O: 基于流,采用阻塞方式,即每次只能处理一个连接。
  • NIO: 基于缓冲区和通道,支持非阻塞操作,并且能够处理多个 I/O 操作。

3.2 NIO 的核心组件

  1. 通道(Channel): NIO 中的通道类似于传统 I/O 中的流,但通道支持双向数据传输。常见的通道类包括:
    • FileChannel:用于文件的读取和写入。
    • SocketChannel:用于网络的客户端和服务端通信。
    • ServerSocketChannel:用于创建服务端套接字通道。
  2. 缓冲区(Buffer): NIO 中的数据读写都通过缓冲区进行,避免了流的每次读取。常见的缓冲区包括:
    • ByteBuffer:用于字节数据的处理。
    • CharBuffer:用于字符数据的处理。
  3. 选择器(Selector): 选择器允许单个线程同时监控多个通道的 I/O 操作。常用于网络 I/O。

3.3 NIO 文件操作示例

示例:使用 FileChannelByteBuffer 读写文件
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;public class FileChannelExample {public static void main(String[] args) {try (RandomAccessFile file = new RandomAccessFile("example.txt", "rw");FileChannel channel = file.getChannel()) {// 写数据到文件ByteBuffer buffer = ByteBuffer.allocate(48);buffer.put("Hello NIO!".getBytes());buffer.flip();channel.write(buffer);// 读数据从文件buffer.clear();channel.read(buffer);buffer.flip();while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}} catch (Exception e) {e.printStackTrace();}}
}

3.4 非阻塞 I/O 示例

示例:使用 Selector 实现多路复用
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;public class NIONonBlockingExample {public static void main(String[] args) throws IOException {Selector selector = Selector.open();ServerSocketChannel serverChannel = ServerSocketChannel.open();serverChannel.configureBlocking(false);serverChannel.bind(new InetSocketAddress(8080));serverChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();Iterator<SelectionKey> keys = selector.selectedKeys().iterator();while (keys.hasNext()) {SelectionKey key = keys.next();keys.remove();if (key.isAcceptable()) {SocketChannel client = serverChannel.accept();client.configureBlocking(false);client.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel client = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(256);client.read(buffer);System.out.println("Received: " + new String(buffer.array()).trim());}}}}
}

四、传统 I/O 与 NIO 的对比

特性传统 I/ONIO
数据处理方式基于流基于缓冲区
阻塞模式阻塞 I/O非阻塞 I/O 和多路复用
线程模型每连接一个线程单线程处理多个连接
性能相对较低,适合小型系统高性能,适合高并发场景
使用复杂度简单易用需要理解更多底层概念
适用场景文件操作、小规模 I/O高并发网络、文件大数据处理

五、总结

  • 通过本文,你了解了 Java I/O 的基础概念、常见类库及其用法,并深入探讨了 NIO 的核心特点与实际应用。在实际开发中:

    • 传统 I/O 适用于小规模、简单的 I/O 场景,使用简单直观。
    • NIO 更适合处理大规模、高并发的 I/O 场景,如高性能的网络服务器和大文件的异步处理。

    希望通过本文的学习,你可以更好地理解和选择适合的 I/O 模型,以提升 Java 开发中的性能和效率!

相关文章:

输入输出(I/O):熟悉 Java 的 I/O 类库,尤其是 NIO 和文件操作

输入输出&#xff08;I/O&#xff09;&#xff1a;熟悉 Java 的 I/O 类库&#xff0c;尤其是 NIO 和文件操作 在 Java 中&#xff0c;I/O&#xff08;输入输出&#xff09;操作是开发中非常重要的一部分&#xff0c;用于与文件、网络和其他数据流交互。Java 提供了传统的 I/O&…...

mysql建立主从集群

mysql建立主从集群需要多个mysql服务器&#xff0c;主从数据库是通过log日志来进行同步的&#xff0c;所以需开启log-bin。本地安装多个mysql参考底部 主数据库配置 打开主数据库my.ini配置文件&#xff0c;给其配置server_id1 [mysqld] port3306 basedirD:/phpstudy_pro/1/…...

Python AI 教程之四:无监督学习

什么是无监督学习? 无监督学习是机器学习的一个分支,用于处理未标记的数据。与监督学习(其中数据被标记为特定类别或结果)不同,无监督学习算法的任务是在不了解数据含义的情况下寻找数据中的模式和关系。这使得无监督学习成为探索性数据分析的强大工具,其目标是了解数据…...

ReactiveStreams、Reactor、SpringWebFlux

注意&#xff1a; 本文内容于 2024-12-28 21:22:12 创建&#xff0c;可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容&#xff0c;请访问原文地址&#xff1a;ReactiveStreams、Reactor、SpringWebFlux。感谢您的关注与支持&#xff01; ReactiveStreams是…...

Qt 的信号槽机制详解:之信号槽引发的 Segmentation Fault 问题拆析(下)

Qt 的信号槽机制详解&#xff1a;之信号槽引发的 Segmentation Fault 问题拆析&#xff08;下&#xff09; 前言一. 信号槽的误用导致崩溃的常见原因1.信号和槽连接的对象被提前释放案例解决方法 2.参数类型不匹配案例解决方法 3. 多线程信号槽使用不当案例解决方法 4. 信号重复…...

opencv(cpp) Mat使用总结

opencv访问矩阵的通道数 #include <opencv2/opencv.hpp> #include <iostream>int main() {// 创建一个3通道的彩色图像&#xff08;例如&#xff0c;BGR格式&#xff09;cv::Mat colorImage cv::Mat::zeros(100, 100, CV_8UC3);// 创建一个单通道的灰度图像cv::M…...

【Hackthebox 中英 Write-Up】Web Request | 分析 HTTP 请求和响应

欢迎来到我的writeup分享&#xff01;我希望大家不要只关注结果或答案&#xff0c;而是通过耐心阅读&#xff0c;尝试逆向工程理解背后的运作原理。在这里&#xff0c;你不仅能找到解题的思路&#xff0c;还能学到更多与Hack The Box等平台相关的技术和技巧&#xff0c;期待与你…...

c#多线程之生产者-消费者模型

在 C# 中实现 生产者-消费者模式&#xff0c;通常需要多个线程来处理数据的生产和消费。我们可以使用 Queue<T> 来作为存储数据的队列&#xff0c;并使用 Thread、Mutex 或 Monitor 来确保线程安全。BlockingCollection<T> 是 C# 提供的一个线程安全的集合&#xf…...

Spring Boot中幂等性的应用

在 Spring Boot 中&#xff0c;幂等性是实现分布式系统设计和接口调用的一个重要概念&#xff0c;尤其在高并发、分布式环境下&#xff0c;确保接口重复调用不会引发系统数据异常至关重要。 幂等性概念 幂等性&#xff08;Idempotence&#xff09;是指一次请求和重复多次请求…...

【机器学习】分类

文章目录 1. 能否用回归解决分类问题2. 生成模型&#xff08;概率生成&#xff09;3. 判别模型&#xff08;逻辑回归&#xff09;4. 多分类问题 1. 能否用回归解决分类问题 二元分类 数据分布不规律&#xff0c;回归函数会尽量减少误差&#xff0c;导致不合理的偏移离分界较远…...

5.若依的角色权限控制

RBAC 基于角色的访问控制&#xff0c;通过角色来分配和管理用户的菜单权限。 修改课程管理的菜单到主类目下 新建角色并分配菜单 新建用户并分配角色 添加一个根菜单&#xff0c;父级为主类目...

Lumos学习王佩丰Excel第二十三讲:饼图美化与PPT图表

一、双坐标柱形图的补充知识 1、主次坐标设置 2、主次坐标柱形避让&#xff08;通过增加两个系列&#xff0c;挤压使得两个柱形挨在一起&#xff09; 增加两个系列 将一个系列设置成主坐标轴&#xff0c;另一个设成次坐标轴 调整系列位置 二、饼图美化 1、饼图美化常见设置 …...

安装winserver2008R2虚拟机步骤

一、服务器系统介绍 1.1什么是服务器&#xff1f; 服务器英文名称为“Server”&#xff0c;指的是网络环境下为客户机(Client)提供某种服务的专用计算机&#xff0c;服务器安装有网络操作系统(如Windows 2000 Server、Linux、Unix等)和各种服务器应用系统软件(如Web服务、电子…...

ACPI PM Timer

ACPI PM Timer 概述&#xff1a; ACPI PM Timer是一个非常简单的计时器&#xff0c;它以 3.579545 MHz 运行&#xff0c;在计数器溢出时生成系统控制中断&#xff08;SCI&#xff09;。它精度较低&#xff0c;建议使用其他定时器&#xff0c;如HPET或APIC定时器。 检测ACPI P…...

Linux 和设备树

“开放固件设备树”&#xff0c;简称 Devicetree (DT)&#xff0c;是一种用于描述硬件的数据结构和语言。更具体地说&#xff0c;它是操作系统可读取的硬件描述&#xff0c;因此操作系统无需对机器的详细信息进行硬编码。 从结构上看&#xff0c;DT 是一棵树&#xff0c;或具有…...

Qt仿音乐播放器:QFileDialog添加本地文件

一、套路 QFileDialog fileDialog(this);// 创建对话框&#xff0c;并设置父元素&#xff1b;fileDialog.setWindowTitle("添加本地下载的音乐");//设置窗口标题//设置文件对话框的默认打开路径 QString projectPathQDir::currentPath();//获取当前目录 QDir dir(pr…...

Odoo 引用字段 fields.Reference:动态关系的选择器

在 Odoo 模型开发中&#xff0c;关系型字段是构建复杂应用的基础。 然而&#xff0c;传统的 m2o、o2m 和 m2m 字段需要在模型定义时就明确指定关系的目标模型&#xff0c;这在某些场景下会显得不够灵活。 为了解决这个问题&#xff0c;Odoo 提供了 fields.Reference 引用字段&a…...

Android笔试面试题AI答之Android基础(6)

Android入门请看《Android应用开发项目式教程》 文章目录 1.Android Studio版本与Gradle版本有什么关联&#xff1f;**1. Gradle 的作用****2. Android Studio 与 Gradle 的关系****3. 版本对应关系****4. 如何查看和修改版本****查看当前版本****修改版本** **5. 版本不兼容的…...

C# 中的记录类型简介 【代码之美系列】

&#x1f380;&#x1f380;&#x1f380;代码之美系列目录&#x1f380;&#x1f380;&#x1f380; 一、C# 命名规则规范 二、C# 代码约定规范 三、C# 参数类型约束 四、浅析 B/S 应用程序体系结构原则 五、浅析 C# Async 和 Await 六、浅析 ASP.NET Core SignalR 双工通信 …...

利用Java爬虫速卖通按关键字搜索AliExpress商品

在这个信息爆炸的时代&#xff0c;数据的价值日益凸显。对于电商领域的从业者来说&#xff0c;能够快速获取商品信息成为了一项重要的技能。速卖通&#xff08;AliExpress&#xff09;作为全球领先的跨境电商平台&#xff0c;拥有海量的商品数据。本文将介绍如何使用Java语言编…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...

大数据驱动企业决策智能化的路径与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;数据驱动的企业竞争力重构 在这个瞬息万变的商业时代&#xff0c;“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...

Qt的学习(二)

1. 创建Hello Word 两种方式&#xff0c;实现helloworld&#xff1a; 1.通过图形化的方式&#xff0c;在界面上创建出一个控件&#xff0c;显示helloworld 2.通过纯代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c; 显示hello world&#xff1b; …...