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

Java学习手册:Java I/O与NIO

Java I/O与NIO

Java I/O(Input/Output)和NIO(New Input/Output)是Java语言中用于处理输入输出操作的重要部分。它们提供了丰富的API来处理文件和网络通信。I/O是Java早期版本中引入的,而NIO是在Java 1.4中引入的,旨在提供更高的性能和更灵活的I/O操作。

Java I/O基础

Java I/O提供了用于读写数据的流(Stream)概念。流可以分为输入流和输出流,分别用于读取和写入数据。Java I/O的主要类位于java.io包中。

输入流与输出流

输入流用于从源读取数据,输出流用于向目的地写入数据。主要的流类包括:

  • InputStreamOutputStream:字节流,用于处理字节数据。
  • ReaderWriter:字符流,用于处理字符数据。
常见的流类
  • FileInputStreamFileOutputStream:用于文件的字节读写。
  • BufferedReaderBufferedWriter:带缓冲的字符流,提高读写效率。
  • ObjectInputStreamObjectOutputStream:用于对象的序列化和反序列化。

示例代码

import java.io.*;

public class IOExample {
    public static void main(String[] args) {
        // 使用FileInputStream读取文件
        try (FileInputStream fis = new FileInputStream("example.txt")) {
            int data;
            while ((data = fis.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 使用BufferedWriter写入文件
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            bw.write("Hello, Java I/O!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Java NIO基础

NIO是在Java 1.4中引入的,旨在提供更高效的I/O操作。NIO引入了通道(Channel)、缓冲区(Buffer)和选择器(Selector)等概念。

通道与缓冲区
  • 通道(Channel):用于读写数据的通道,类似于传统的流,但支持双向操作。
  • 缓冲区(Buffer):用于存储数据的容器,数据在通道和缓冲区之间传输。

常见的通道类包括:

  • FileChannel:用于文件的读写。
  • SocketChannel:用于网络通信。
  • ServerSocketChannel:用于监听网络连接。

示例代码

import java.io.*;
import java.nio.*;
import java.nio.channels.*;

public class NIOExample {
    public static void main(String[] args) {
        // 使用FileChannel读取文件
        try (FileChannel fileChannel = FileChannel.open(Paths.get("example.txt"))) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (fileChannel.read(buffer) != -1) {
                buffer.flip(); // 切换到读模式
                while (buffer.hasRemaining()) {
                    System.out.print((char) buffer.get());
                }
                buffer.clear(); // 清空缓冲区
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 使用FileChannel写入文件
        try (FileChannel fileChannel = FileChannel.open(Paths.get("output.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
            String content = "Hello, Java NIO!";
            ByteBuffer buffer = ByteBuffer.wrap(content.getBytes());
            fileChannel.write(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

NIO的选择器

选择器(Selector)用于监听多个通道的事件(如:连接打开、数据到达),是实现单线程管理多个网络连接的关键。

示例代码

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;

public class SelectorExample {
    public static void main(String[] args) {
        try {
            // 创建ServerSocketChannel并绑定端口
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.bind(new InetSocketAddress(8080));
            serverChannel.configureBlocking(false);

            // 创建Selector
            Selector selector = Selector.open();
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            while (true) {
                // 等待事件发生
                selector.select();
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectedKeys.iterator();

                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();

                    if (key.isAcceptable()) {
                        // 处理新的连接
                        ServerSocketChannel server = (ServerSocketChannel) key.channel();
                        SocketChannel clientChannel = server.accept();
                        clientChannel.configureBlocking(false);
                        clientChannel.register(selector, SelectionKey.OP_READ);
                        System.out.println("新连接: " + clientChannel.getRemoteAddress());
                    } else if (key.isReadable()) {
                        // 处理读取数据
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int bytesRead = clientChannel.read(buffer);
                        if (bytesRead > 0) {
                            buffer.flip();
                            System.out.println("收到数据: " + new String(buffer.array(), 0, bytesRead));
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Java 7的NIO.2

Java 7引入了NIO.2,提供了更丰富的文件系统操作API,位于java.nio.file包中。

示例代码

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;

public class NIO2Example {
    public static void main(String[] args) {
        Path path = Paths.get("example.txt");

        // 检查文件是否存在
        if (Files.exists(path)) {
            // 读取文件内容
            try {
                List<String> lines = Files.readAllLines(path);
                for (String line : lines) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 写入文件内容
        try {
            List<String> lines = Arrays.asList("Hello, Java NIO.2!", "This is a test.");
            Files.write(path, lines, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 获取文件属性
        try {
            BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
            System.out.println("文件大小: " + attributes.size());
            System.out.println("创建时间: " + attributes.creationTime());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结

Java I/O和NIO提供了丰富的API来处理文件和网络通信。I/O适合简单的文件和网络操作,而NIO适合高性能和复杂的I/O场景。通过掌握这些API,开发者可以高效地处理各种输入输出需求。

希望本文能帮助读者深入理解Java I/O和NIO的使用方法和最佳实践,从而在实际开发中更加高效地处理数据传输和存储。

相关文章:

  • 【题解-洛谷】P1824 进击的奶牛
  • LangSmith 设置指南
  • 安装树莓派3B+环境
  • 山东大学软件学院创新项目实训开发日志(12)之将对话记录保存到数据库中
  • OSI 七层模型与 TCP/IP 协议栈详解
  • 【JS】关于原型/原型链
  • 【玩泰山派】MISC(杂项)- 使用vscode远程连接泰山派进行开发
  • 0x05.为什么 Redis 设计为单线程?6.0 版本为何引入多线程?
  • 移动端适配
  • javaSE.Lambda表达式
  • 【TI MSPM0】Printf重定向学习
  • GitLab 17.x 配置 https
  • NLP 梳理02 — 标点符号和大小写
  • BUUCTF-web刷题篇(25)
  • 【Ansible自动化运维】五、ansible 的高级特性与扩展:应对复杂场景
  • 互联网三高-数据库高并发之分库分表ShardingJDBC
  • 【CVE-2024-7881】ARM CPU漏洞安全通告
  • LangChain-提示模板 (Prompt Templates)
  • 【力扣hot100题】(098)下一个排列
  • 理想汽车MindVLA自动驾驶架构核心技术梳理
  • 湖南慈利一村干部用AI生成通知并擅自发布,乡纪委立案
  • 上百家单位展示AI+教育的实践与成果,上海教育博览会开幕
  • 打击网络侵权盗版!四部门联合启动“剑网2025”专项行动
  • 淄博一酒店房间内被曝发现摄像头,当地警方已立案调查
  • 再现五千多年前“古国时代”:凌家滩遗址博物馆今开馆
  • 阿里上季度营收增7%:淘天营收创新高,AI产品营收连续七个季度三位数增长