NIO学习–核心概念与基本读写

转载自 NIO学习–核心概念与基本读写

这两天花了时间学习了java的nio,看的书是Ron Hitchens著的 《Java NIO》,总的来说,这本书真的写的非常好,而且整本书将java nio的内容从底层讲了个遍,书不厚,但是确实值得一读,这里总结一下学习后的一些心得。学习过程中既详细看完了《Java NIO》这本书,同时也参照了http://zhangshixi.iteye.com/blog/679959该作者写的关于NIO的博文。好了,我们正式开始NIO的学习吧。

首先,简单说说I/O和NIO一些概念性的东西吧。

I/O流或者输入/输出流指的是计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。新的输入/输出(NIO)库是在JDK 1.4中引入的。NIO弥补了原来的I/O的不足,它在标准Java代码中提供了高速的、面向块的I/O。原来的I/O库与NIO最重要的区别是数据打包和传输的方式的不同,原来的 I/O 以流 的方式处理数据,而 NIO 以块 的方式处理数据。 面向流的I/O系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤 器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的I/O通常相当慢。
NIO与原来的I/O有同样的作用和目的,但是它使用块I/O的处理方式。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的I/O缺少一些面向流的I/O所具有的优雅性和简单性。

我们首先从一个例子开始NIO的学习

我们分别用I/O以及NIO来实现从一个文件中读取内容并将其打印出来,看看I/O和NIO的特点。

使用IO来读取指定文件中的前1024字节并打印出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
 * 使用IO读取指定文件的前1024个字节的内容。
 * @param args
 * @throws Exception
 */
public static void main(String[] args) throws Exception
{
    FileInputStream is = new FileInputStream("GitHub.txt");
    byte[] buffer = new byte[1024];
    is.read(buffer);
    System.out.println(new String(buffer));
    is.close();
}
/**
 * 使用NIO读取指定文件的前1024个字节的内容。
 * @param args
 * @throws Exception
 */
public static void main(String[] args) throws Exception
{
    FileInputStream is = new FileInputStream("GitHub.txt");
    //为该文件输入流生成唯一的文件通道  FileChannel
    FileChannel channel = is.getChannel();
    //开辟一个长度为1024的字节缓冲区
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    channel.read(buffer);
    System.out.println(new String(buffer.array()));
    System.out.println(buffer.isDirect() + ", " + buffer.isReadOnly());
    channel.close();
    is.close();
}

从上面的例子中可以看出,NIO以通道Channel和缓冲区Buffer为基础来实现面向块的IO数据处理。下面将讨论并学习NIO 库的核心概念以及从高级的特性到底层编程细节的几乎所有方面。

NIO中的读和写

1)    概述:
读和写是I/O的基本过程。从一个通道中读取很简单:只需创建一个缓冲区,然后让通道将数据读到这个缓冲区中。写入也相当简单:创建一个缓冲区,用数据填充它,然后让通 道用这些数据来执行写入操作。

2)    从文件中读取:
如果使用原来的I/O,那么我们只需创建一个FileInputStream并从它那里读取。而在NIO中,情况稍有不同:我们首先从FileInputStream获取一个FileChannel对象,然后使用这个通道来读取数据。
在NIO系统中,任何时候执行一个读操作,您都是从通道中读取,但是您不是直接从通道读取。因为所有数据最终都驻留在缓冲区中,所以您是从通道读到缓冲区中。
因此读取文件涉及三个步骤:
(1) 从FileInputStream获取Channel。
(2) 创建Buffer。
(3) 将数据从Channel读到Buffer 中。
现在,让我们看一下这个过程。

1
2
3
4
5
6
7
// 第一步是获取通道。我们从 FileInputStream 获取通道:  
FileInputStream fin = new FileInputStream( "readandshow.txt" ); 
FileChannel fc = fin.getChannel(); 
// 下一步是创建缓冲区:  
ByteBuffer buffer = ByteBuffer.allocate( 1024 ); 
// 最后,需要将数据从通道读到缓冲区中:  
fc.read( buffer );

您会注意到,我们不需要告诉通道要读多少数据到缓冲区中。每一个缓冲区都有复杂的内部统计机制,它会跟踪已经读了多少数据以及还有多少空间可以容纳更多的数据。我们将在缓冲区内部细节中介绍更多关于缓冲区统计机制的内容。

3)    写入文件:
在 NIO 中写入文件类似于从文件中读取。

1
2
3
4
5
6
7
8
9
10
11
// 首先从 FileOutputStream 获取一个通道:  
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" ); 
FileChannel fc = fout.getChannel(); 
// 下一步是创建一个缓冲区并在其中放入一些数据,这里,用message来表示一个持有数据的数组。  
ByteBuffer buffer = ByteBuffer.allocate( 1024 ); 
for (int i=0; i<message.length; ++i) { 
     buffer.put( message[i] ); 
buffer.flip(); 
// 最后一步是写入缓冲区中:  
fc.write( buffer );

注意在这里同样不需要告诉通道要写入多数据。缓冲区的内部统计机制会跟踪它包含多少数据以及还有多少数据要写入。

4)    读写结合:
最后将展示使用读写结合,将一个文件的所有内容拷贝到另一个文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
 * 将一个文件的所有内容拷贝到另一个文件中。
 
 * CopyFile.java 执行三个基本操作:
 * 首先创建一个 Buffer,然后从源文件中将数据读到这个缓冲区中,然后将缓冲区写入目标文件。
 * 程序不断重复 — 读、写、读、写 — 直到源文件结束。
 *  */ 
public class CopyFile { 
    public static void main(String[] args) throws Exception { 
        String infile = "GitHub.txt"
        String outfile = "GitHub2.txt"
        // 获取源文件和目标文件的输入输出流 
        FileInputStream fin = new FileInputStream(infile); 
        FileOutputStream fout = new FileOutputStream(outfile); 
        // 获取输入输出通道 
        FileChannel fcin = fin.getChannel(); 
        FileChannel fcout = fout.getChannel(); 
        // 创建缓冲区 
        ByteBuffer buffer = ByteBuffer.allocate(1024); 
        while (true) { 
            // clear方法重设缓冲区,使它可以接受读入的数据 
            buffer.clear(); 
            // 从输入通道中将数据读到缓冲区 
            int r = fcin.read(buffer); 
            // read方法返回读取的字节数,可能为零,如果该通道已到达流的末尾,则返回-1 
            if (r == -1) { 
                break
            
            // flip方法让缓冲区可以将新读入的数据写入另一个通道 
            buffer.flip(); 
            // 从输出通道中将数据写入缓冲区 
            fcout.write(buffer); 
        
    
}

下一篇我们将会深度讲解一下NIO中的缓冲区Buffer。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329935.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python3安装mysql模块_Python安装MySQL库详解,步骤及错误的解决方法

前面我们介绍的Python网络爬虫通常将抓取的数据存储至TXT或CSV文件&#xff0c;而当数据量增加之时&#xff0c;就需要将其存储至本地数据库了。Python访问数据库需要对应的接口程序&#xff0c;我们可以把接口程序理解为Python的一个模块&#xff0c;它提供了数据库客户端的接…

centos8安装docker

【README】本文参考了 docker官方文档安装指南&#xff0c; Install Docker Engine on CentOS | Docker DocumentationInstructions for installing Docker Engine on CentOShttps://docs.docker.com/engine/install/centos/ 【1】安装前的工作 1.需要centos7或8上&#xff1b…

34.在排序数组中查找元素的第一个和最后一个位置--leetcode算法题解(带注释)

public int[] searchRange(int[] nums, int target) {//先决条件排除一部分if(target < nums[0] || target > nums[nums.length - 1]){return new int[]{-1,-1};}//初始化左右边界int l 0;int r nums.length - 1;//初始化数组int[] arr {-1,-1};int mid 0;//代表左边…

datagridview绑定数据源不显示_sharding-jdbc系列之 数据源配置(一)

spring boot Yaml方式Bean定义一个Config类&#xff0c;配置数据源&#xff0c;上面的代码很简单&#xff0c;无非就是获取yaml文件&#xff0c;然后通过YmlByteArrayDataSource创建一个dataSource public YmlByteArrayDataSource继承了ShardingDataSource&#xff0c;调用了su…

关于 NIO 你不得不知道的一些“地雷”

转载自 关于 NIO 你不得不知道的一些“地雷”本文是笔者在学习NIO过程中发现的一些比较容易让人忽略的知识的一个总结&#xff0c;而这些让人忽略的小细节恰恰是NIO网络编程中必不可少。虽然现在我们不会直接编写NIO来完成我们的网络层通讯&#xff0c;而是使用成熟的基于NIO的…

转:Centos防火墙设置与端口开放的方法

转自&#xff1a; Centos防火墙设置与端口开放的方法_tianxin的专栏-CSDN博客Centos升级到7之后&#xff0c;内置的防火墙已经从iptables变成了firewalld。所以&#xff0c;端口的开启还是要从两种情况来说明的&#xff0c;即iptables和firewalld。更多关于CentOs防火墙的最新…

583. 两个字符串的删除操作用时6ms的另类解法

开门见山 看见这道题&#xff0c;我的第一反应不是去找出符合这道题的动态规划递推公式&#xff0c;我反而认为可以借用一下1143. 最长公共子序列的题解 class Solution {public int longestCommonSubsequence(String text1, String text2) {int[][] dp new int[text1.lengt…

Java 非阻塞 IO 和异步 IO

转载自 Java 非阻塞 IO 和异步 IO上一篇文章介绍了 Java NIO 中 Buffer、Channel 和 Selector 的基本操作&#xff0c;主要是一些接口操作&#xff0c;比较简单。 本文将介绍非阻塞 IO 和异步 IO&#xff0c;也就是大家耳熟能详的 NIO 和 AIO。很多初学者可能分不清楚异步和非阻…

element js 包含字符_selenium3.x(10)js弹框处理

web应用中&#xff0c;经常会遇到弹框。不处理弹框&#xff0c;页面其他元素都是不能操作的。js弹框有3种&#xff1a;alert警告框、confirm确认窗口、prompt信息输入窗口。webdriver提供了处理这3种弹框的方法。首先通过switch_to定位到弹框&#xff0c;然后针对弹框的不同&am…

转:centos8开启防火墙端口

转自&#xff1a; Centos8开放防火墙端口_Programmer-Awei的博客-CSDN博客查看防火墙某个端口是否开放firewall-cmd --query-port3306/tcp开放防火墙端口3306firewall-cmd --zonepublic --add-port3306/tcp --permanent查看防火墙状态systemctl status firewalld关闭防火墙sys…

AQS的细节--自用,非正常教程

AQS的概念 AQS叫抽象队列同步器&#xff0c;是一个框架&#xff0c;我们可以在JUC很多包看见AQS的具体实现&#xff0c;比如锁和读写锁&#xff0c;condition等&#xff0c;具有可扩展性&#xff0c;可以根据此自定义同步工具类&#xff0c;优点是系统开销低&#xff0c;实现锁…

mininet编程实现交换机规则的插入、删除与修改。_可编程网卡芯片在滴滴云网络的应用实践...

桔妹导读&#xff1a;随着云规模不断扩大以及业务层面对延迟、带宽的要求越来越高&#xff0c;采用DPDK 加速网络报文处理的方式在横向纵向扩展都出现了局限性。可编程芯片成为业界热点。本文主要讲述了可编程网卡芯片在滴滴云网络中的应用实践&#xff0c;遇到的问题、带来的收…

centos8上docker tomcat容器访问报404解决方法

目录 【README】 【1】docker安装tomcat 【2】启动多个tomcat容器 【README】 1.本文记录了 访问docker tomcat容器报404的解决方法&#xff1b; 2.附带安装tomcat步骤&#xff1b; 3.centos8 安装docker&#xff0c;refers2 centos8安装docker_PacosonSWJTU的博客-CSDN博…

ConcurrentHashMap--自用,非教学

结论先行&#xff0c;细节在下面 jdk1.7是如何解决并发问题的以及完整流程 一.首先new一个concurrentHashMap 调用默认构造方法 二.初始化 初始化initialCapacity&#xff08;默认是16&#xff0c;指一个segment内Entry的数量&#xff09;&#xff0c;loadFactor&#xff…

Java开发必须掌握的线上问题排查命令

转载自 Java开发必须掌握的线上问题排查命令作为一个合格的开发人员&#xff0c;不仅要能写得一手还代码&#xff0c;还有一项很重要的技能就是排查问题。这里提到的排查问题不仅仅是在coding的过程中debug等&#xff0c;还包括的就是线上问题的排查。由于在生产环境中&#x…

centos8启动docker-mysql8容器

【README】 本文记录了 centos8 安装&#xff0c;启动mysql8的docker容器的步骤&#xff1b; 【1】安装mysql8 docker容器 步骤1&#xff0c; 查看mysql8 docker镜像版本 &#xff1b; 最简单的方式是上 Docker Hubhttps://hub.docker.com/直接搜索mysql&#xff0c;查看其 …

Java命令学习系列(一)——Jps

转载自 Java命令学习系列&#xff08;一&#xff09;——Jpsjps位于jdk的bin目录下&#xff0c;其作用是显示当前系统的java进程情况&#xff0c;及其id号。 jps相当于Solaris进程工具ps。不象"pgrep java"或"ps -ef grep java"&#xff0c;jps并不使用应用…

springboot2.5.5配置druid数据源1.2.8与jdbc

【README】 本文记录了 springboot配置 druid数据源的步骤&#xff1b; 【1】新建springboot项目并配置druid 步骤1&#xff0c;新建springbt项目 步骤2&#xff0c;选择spring web&#xff0c;jdbc&#xff0c;mysql驱动依赖&#xff1b; 步骤3&#xff0c;添加 druid数据源…

tsc244标签编辑软件_能打小票的标签机,M110智能标签打印机来了!

每张被贴上的标签背后&#xff0c;都是对待梦想的认真、对待生活的用心&#xff0c;M110智能标签打印机为你标记美好&#xff0c;实现品质与效率兼得的追求。01、 产品简介M110智能标签打印机采取热敏无墨打印技术&#xff0c;无需碳带&#xff0c;便捷经济&#xff0c;配套“标…

面试官:简述实现一个线程池的设计思路

前言 二面碰到这个问题人都麻了&#xff0c;我扯了好多没用的&#xff0c;面后赶紧来补一下&#xff0c;但是找到的基本都是一堆纯代码&#xff0c;不是讲思路的。下面的思路是我参考美团技术团队文章后总结的。 具体思路 一、总体设计 线程池在内部实际上构建了一个生产者…