首页 > 编程语言 >五、I/O与网络编程-5.1、I/O基础

五、I/O与网络编程-5.1、I/O基础

时间:2024-09-19 20:52:59浏览次数:12  
标签:5.1 java NIO 编程 网络 事件 import 字节 String

5.1、I/O基础

5.1.1、Java有几种文件拷贝方式,哪一种效率最高?

答:
以下是三种不同方式的Java代码示例:

  1. 使用字节流进行传输:可以使用FileInputStream和FileOutputStream类来完成文件的读取和写入,逐字节地拷贝文件内容。这种方式比较简单,但效率较低,特别是对于大文件而言。
示例:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamCopy {
    public static void main(String[] args) {
        String sourceFile = "source.txt";
        String destFile = "dest.txt";

        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(destFile)) {
            int byteData;
            while ((byteData = fis.read()) != -1) {
                fos.write(byteData);
            }
            System.out.println("文件拷贝完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  1. 使用缓冲区进行传输:可以使用BufferedInputStream和BufferedOutputStream类,结合字节数组进行文件的读取和写入操作。这种方式比较高效,因为可以减少实际的I/O操作次数。
示例:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedStreamCopy {
    public static void main(String[] args) {
        String sourceFile = "source.txt";
        String destFile = "dest.txt";

        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile))) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            System.out.println("文件拷贝完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  1. 使用NIO进行传输:可以使用java.nio包中的Channel和Buffer类来实现文件的读写操作。这种方式使用了直接内存缓冲区,能够更好地利用操作系统底层的文件传输机制,因此效率更高。
示例:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class NIOCopy {
    public static void main(String[] args) {
        String sourceFile = "source.txt";
        String destFile = "dest.txt";

        Path sourcePath = Path.of(sourceFile);
        Path destPath = Path.of(destFile);

        try {
            Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("文件拷贝完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用NIO进行文件拷贝的效率最高,尤其是对于大文件而言。使用字节流进行传输的效率较低,特别是在处理大文件时,可能会导致内存溢出的问题。使用缓冲区进行传输的效率稍微高一些,但仍然比不上NIO方式。

扩展:
在Java中,使用缓冲区进行传输比使用字节流进行传输效率更高的原因如下:

  1. 减少对底层I/O设备的访问次数:使用字节流进行传输时,每次读取或写入数据都会直接与底层I/O设备进行交互,这会导致频繁的设备访问。而使用缓冲区传输时,数据会先被写入到缓冲区中,然后再一次性地与底层I/O设备进行交互。这样可以减少对底层I/O设备的访问次数,提高效率。
  2. 提高数据读写的速度:使用字节流进行传输时,每次读取或写入数据都是以一个字节为单位进行操作,这会导致频繁的读写操作。而使用缓冲区传输时,可以一次性读取或写入一定量的数据,大大提高了数据读写的速度。
  3. 减少系统调用次数:使用字节流进行传输时,每次读取或写入数据都会触发系统调用,并涉及到内核态和用户态的切换。而使用缓冲区传输时,减少了系统调用的次数,减少了系统资源的消耗。
  4. 提供了更灵活的读写方式:缓冲区提供了一系列的读写方法,可以根据实际需求来选择不同的读写方式。可以通过一次性读取或写入多个字节来提高效率,也可以使用标记和重置等方法来回退或跳过数据。

5.1.2、I/O和NIO的区别是什么?

答:
在Java中,I/O(输入/输出)和NIO(新I/O)是两种不同的输入输出模型。它们的区别在于以下几个方面:

  1. I/O是基于流(Stream)的模型,而NIO是基于缓冲区(Buffer)的模型。I/O通过流按照字节序列一个接一个地处理数据,而NIO通过将数据先读入缓冲区,然后再进行处理。

  2. I/O是面向字节的,而NIO是面向块(Block)的。I/O以字节为单位进行读写操作,而NIO以块为单位进行读写操作,一个块可以包含多个字节。

  3. I/O是阻塞式的,而NIO是非阻塞式的。在I/O中,当进行读操作时,如果没有数据可读,线程将被阻塞,直到有数据可读。而在NIO中,当进行读操作时,如果没有数据可读,线程不会被阻塞,可以继续执行其他操作。

  4. I/O是单向的,而NIO是双向的。在I/O中,一个流只能作为读流或写流使用,而在NIO中,一个通道(Channel)可以同时用于读和写。

扩展:
I/O适用于低负载、低并发的场景,而NIO适用于高负载、高并发的场景。使用NIO可以提供更高的吞吐量和更低的延迟。

5.1.3、谈谈你对I/O多路复用机制的理解

答:
I/O多路复用是指通过一个线程来管理多个I/O事件的机制。在Java中,可以使用NIO的Selector来实现I/O多路复用。

I/O多路复用的基本原理是通过一个线程同时监听多个输入流的可读、可写等事件,当某个输入流有事件发生时,就会通知线程进行处理,从而实现同时处理多个I/O事件的能力
在Java中,使用Selector类来创建一个选择器,然后将多个通道(Channel)注册到选择器上。在循环中调用选择器的select()方法,该方法会阻塞直到至少有一个通道有事件发生。然后通过selectedKeys()方法获取发生事件的通道集合,进行相应的处理。

使用NIO的Selector实现多路复用的示例:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NioMultiplexingServer {
    public static void main(String[] args) throws IOException {
        // 创建ServerSocketChannel,并绑定到指定端口
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8888));
        serverSocketChannel.configureBlocking(false);

        // 创建Selector,并注册ServerSocketChannel的ACCEPT事件
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 阻塞等待事件发生
            int readyChannels = selector.select();

            if (readyChannels == 0) {
                continue;
            }

            // 获取发生事件的SelectionKey集合
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();

            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();

                if (selectionKey.isAcceptable()) {
                    // 处理ACCEPT事件
                    ServerSocketChannel serverChannel = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel socketChannel = serverChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) {
                    // 处理READ事件
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    socketChannel.read(buffer);
                    buffer.flip();
                    String data = new String(buffer.array()).trim();
                    System.out.println("Received data: " + data);
                    socketChannel.close();
                }

                // 从集合中删除已处理的SelectionKey
                iterator.remove();
            }
        }
    }
}
首先创建了一个ServerSocketChannel,并将其绑定到指定端口。
然后创建了一个Selector,并注册ServerSocketChannel的ACCEPT事件。
在主循环中,调用Selector的select()方法阻塞等待事件发生,当有事件发生时,
通过selectedKeys()方法获取发生事件的SelectionKey集合,并遍历处理。
如果是ACCEPT事件,则调用accept()方法获取SocketChannel,并将其注册到Selector上以监听READ事件。
如果是READ事件,则从SocketChannel中读取数据并处理,然后关闭SocketChannel。

I/O多路复用的优点是能够同时处理多个I/O事件,而且不需要创建多个线程来处理每个事件,从而节省了系统资源。它适用于需要同时处理多个连接的高并发场景。

扩展:
I/O多路复用也有一些限制。首先,它对于处理一些复杂的逻辑可能不够灵活,因为它只关注事件的发生而并不关心事件的具体内容。其次,如果某个事件的处理时间过长,会影响其他事件的处理速度。因此,在使用I/O多路复用时需要考虑事件处理的效率和逻辑复杂度。

标签:5.1,java,NIO,编程,网络,事件,import,字节,String
From: https://blog.csdn.net/weixin_61769871/article/details/142367742

相关文章

  • 南大通用GBase 8s 集群网络交互信息概述(上)
    在当今数据驱动的商业环境中,数据库的性能和可靠性是企业成功的关键。GBase8s作为一款的国产数据库系统,其SSC集群架构通过优化网络交互,显著提升了性能和可用性。本文将分两部分聚焦于GBase8sSSC集群的网络交互信息概述和网络吞吐量计算。在GBase 8sSSC集群中,主节点向从节点只传......
  • 南大通用GBase 8s 集群网络交互信息概述(下)
    在上篇文章中,我们了解了GBase8sSSC集群的网络交互机制。本文将聚焦于网络吞吐量的计算,分析SSC集群在不同业务场景下的表现,并与HAC和RHAC集群进行对比。一、无业务场景下的网络吞吐量在无业务时,网络上只有每秒发送的心跳包和心跳包的ACK,则网络吞吐量极低,具体为(114+86)/(1024*1024......
  • 哪个编程工具让你的工作效率翻倍?
    在日益繁忙的工作环境中,选择合适的编程工具已成为提升开发者工作效率的关键。不同的工具能够帮助我们简化代码编写、自动化任务、提升调试速度,甚至让团队协作更加顺畅。那么,哪款编程工具让你的工作效率翻倍?是智能的代码编辑器,强大的版本控制工具,还是那些让你事半功倍的自动化......
  • Java毕业设计-基于SSM框架的网络办公系统项目实战(附源码+论文)
    大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。......
  • 自学黑客(网络安全),一般人我劝你还是算了吧
     我是一名8年半的网安工程师“老司机”,要给准备入坑的同学泼盆冷水了,网络安全真的不是一般人能学的。有人会问“你一个8年的网安老司机,为什么还给大家泼冷水”?好多人说:网安基础很简单,是个人稍微认真点都能懂,给网安打上了简单、易懂的标签。然后上来就是一波言论浮夸的输出,......
  • 2024年入职/转行网络安全,该如何规划?_网络安全职业规划
     前言前段时间,知名机构麦可思研究院发布了 《2022年中国本科生就业报告》,其中详细列出近五年的本科绿牌专业,其中,信息安全位列第一。网络安全前景对于网络安全的发展与就业前景,想必无需我多言,作为当下应届生收入较高的专业之一,网络安全同样也在转行领域中占据热门位置,主要......
  • 花8000元去培训机构学习网络安全值得吗,学成后就业前景如何?
      我就是从培训机构学的网络安全,线下五六个月,当时学费不到一万,目前已成功入行。所以,只要你下决心要入这一行,过程中能好好学,那这8000就花得值~因为只要学得好,工作两个多月就能赚回学费,而且大部分培训班也会有就业支持,比如老师给推荐或者定期的招聘会…先说一下我自己,很喜欢......
  • Java语言程序设计基础篇_编程练习题**18.31 (替换单词)
    目录题目:**18.31(替换单词)习题思路代码示例 运行结果替换前替换后题目:**18.31(替换单词) 编写一个程序,递归地用一个新单词替换某个目录下的所有文件中出现的某个单词。从命令行如下传递参数:javaExercise18_31dirNameoldWordnewWord习题思路(读取路径方......
  • 网络工程师学习笔记——网络互连与互联网(二)
    IP地址是电脑在互联网上进行进行通信的“身份证”是网络号+主机号网络号代表所处的网段,而主机号则代表电脑ipv4有232个ip地址大约43亿其中又分为A、B、C、D、E类地址A:1.0.0.0~127.255.255.255(首位0)B:128.0.0.0~191.255.255.255(10)C:192.0.0.0~223.255.255.255(110)D:224.0.0......
  • 云服务器独立佣金:稳固网络时代的关键
    在现代商业环境中,网络基础设施的稳定性和安全性至关重要。服务器独立佣金作为一种新兴的网络管理方法,正在迅速被各行业采纳。本篇文章将详述其基本概念、主要优点以及实施指南,帮助企业更好地利用这一创新模式。基本概念服务器独立佣金指的是将网络服务器管理和操作的责任分布给独立......