java nio剖析

java nio剖析

 

java nio
的全称是
java new I/O
,即一个全新的
I/O
控制系统,它的
API
的包名为
java.nio
,是在
jdk1.4
后引入的。
nio
之所以为为新,在于它并没在原来
I/O
的基础上进行开发,而是提供了全新的类和接口,除了原来的基本功能之外,它还提供了以下新的特征:
       
 
多路选择的非封锁式
I/O
设施
        

支持文件锁和内存映射
       

支持基于
Perl
风格正则表达式的模式匹配设施
       

字符集编码器和译码器
       
为了支持这些新的功能,
nio
使用了两个新的概念:
          1.
信道
(channel)
              
信道是一个连接,可用于接收或发送数据,如文件和套接字。因为信道连接的是底层的物理设备,他可以直接支持设备的读
/
写,或提供文件锁。对于文件、管道、套接字都存在相应的信道类。可以把信道看成是数据流的替代品。信道没有包装类,提高了性能。
            
所有的信道类都位于
java.nio.channels
包中。
         2.
缓冲区
(buffer)
              
缓冲区是一个数据容器。可以把它看做内存中的一个大的数组,用来存储来自信道的同一类型的所有数据,因此,程序员可以使用字节、字符、整数等缓冲区。字节缓冲区提供必要的方法,可以提取或存入所有基本类型
(boolean
型除外
)
的数据。 
              buffer
类的核心是一块内存区,便于核心代码和
java
代码同时访问,核心代码可以直接访问它,
java
代码可以通过
API
访问它。
            
缓冲区基本上是一块内存区域,因而可以执行一些与内存有关的操作,如清除其中的内容,支持读写或只读操作等。
            
所有的
buffer
类都位于
java.nio
包中。
       
下面看如何使用它们:
1.     
使用信道
在信道的使用中,文件的信道是最具有代表性的,
API
也是最多的,下面我们以文件信道为例介绍它。
    
获取文件信道
文件的信道的类为FileChannel,遗憾的是他并没有向我们提供打开文件的方法,我们可以通过调用FileInputStream、FileOutputStream和RandomAccessFile类实例的getChannel()方法来获取其实例。例如:
RandomAccessFile raf = new RandomAccessFile(“data.txt”, “rw”);
FileChannel fc = raf.getChannel();
请注意,这里打开文件的方式如”rw”将适用于文件信道,FileInputStream实例的getChannel()方法所获得的通道将允许进行读取操作。通过FileOutputStream的getChannel方法所获得的通道将允许进行写入操作。最后,如果使用模式
"r" 创建 RandomAccessFil的实例,则通过该实例的getChannel()方法所获得的通道将允许进行读取操作,如果使用模式
"rw" 创建实例,则获得的通道将允许进行读取和写入操作。

    从信道读取数据
读取的数据会默认放到字节缓冲区中。
FileChannel提供了四个API读取数据:
a.
   
read(ByteBuffer dst) 将字节序列从此通道读入给定的缓冲区
b.  
read(ByteBuffer[] dsts) 将字节序列从此通道读入给定的缓冲区
c.   
read(ByteBuffer[] dsts, int offset, int length)

          将字节序列从此通道读入给定缓冲区的子序列中
d.   
read(ByteBuffer dst, long position)

          从给定的文件位置开始,从此通道读取字节序列,并写入给定的缓冲区
   
向信道写入数据
数据来源默认是字节缓冲区。
FileChannel
提供了四个
API
写入数据:
a.
write(ByteBuffer src)

          将字节序列从给定的缓冲区写入此通道
b.
write(ByteBuffer[] srcs)

          将字节序列从给定的缓冲区写入此通道
c.
write(ByteBuffer[] srcs, int offset, int length)

          将字节序列从给定缓冲区的子序列写入此通道
d.
write(ByteBuffer src, long position)

          从给定的文件位置开始,将字节序列从给定缓冲区写入此通道
          
 
● 使用文件锁
              
文件锁机制主要是在多线程同时读写某个文件资源时使用。
               FileChannel
提供了两种加锁机制,lock和tryLock,两者的区别在于,lock是同步的,
               直至成功才返回,tryLock是异步的,无论成不成功都会立即返回。
           
● 使用内存映射

                 FileChannel
提供的的
API
为:
                 MappedByteBuffer
map(FileChannel.MapMode mode,   long position, long size);
                      映射模式一个有三种:
                      a.只读: 试图修改得到的缓冲区将导致抛出
ReadOnlyBufferException
.(MapMode.READ_ONLY)
          b.读 /写
对得到的缓冲区的更改最终将传播到文件;该更改对映射到同一文件的其他程序不一定是可见的。 (
MapMode.READ_WRITE)
                      c.专用
对得到的缓冲区的更改不会传播到文件,并且该更改对映射到同一文件的其他程序也不是可见的;相反,会创建缓冲区已修改部分的专用副本。 (
MapMode.PRIVATE)
2.      使用缓冲区
     层次结构
所有缓冲区的基类都是Buffer,Boolean类型外,其它数据类型都有对应的缓冲区类,
另有一个ByteOrder类,用来设置缓冲区的大小端顺序,即BigEndian或者是LittleEndian
默认情况下是BigEndian。其层次结构图如下:
java nio剖析
     获取缓冲区对象
一共有两种类型的缓冲区,直接缓冲区和非直接缓冲区,两者区别在于直接缓冲区上的数据操作,
虚拟机将尽量使用本机I/O,并尽量避免使用中间缓冲区。判断一个缓冲区是否是直接缓冲区,
可以调用isDirect()方法。
有三种方式来获取一个缓冲区的对象:
a.      调用allocate()或者allocateDirect()方法直接分配,其中allocateDirect()
返回的是直接缓冲区。
b.      包装一个数组,如:
byte[] b = new byte[1024];
ByteBuffer bb = ByteBuffer.wrap(b);
c.       内存映射,即调用FileChannelmap()方法。
     缓冲区基本属性
这几个属性是每个缓冲区都有的并且是常用的操作。
a.     容量(capacity),缓冲区大小
b.      限制(limit),第一个不应被读取或写入的字节的索引,总是小于容量。
c.       位置(position),下一个被读取或写入的字节的索引,总是小于限制。
d.      clear()方法:设置limit为capacity,position为0。
e.      filp()方法:设置limit为当前position,然后设置position为0。
f.        rewind()方法:保持limit不变,设置position为0。
     缓冲区数据操作
操作包括了读取和写入数据两种。
读取数据使用get()及其系列方法,除boolean外,每一种类型包括了对应的get()方法,
如getInt(),getChar()等,get()方法用来读取字节,支持相对和绝对索引两种方式。
写入数据使用put()及其系列方法,和get()方法是对应的。
           下面这个例子演示了如何使用缓冲区和信道:

java nio剖析 package  nio;
java nio剖析
java nio剖析
import  java.io.FileInputStream;
java nio剖析
import  java.io.FileOutputStream;
java nio剖析
import  java.nio.ByteBuffer;
java nio剖析
import  java.nio.channels.FileChannel;
java nio剖析
java nio剖析
public   class  BufferDemo  {
java nio剖析
java nio剖析    
java nio剖析    
public static void main(String[] args) throws Exception{
java nio剖析        
//分配一个非直接缓冲区
java nio剖析
        ByteBuffer bb = ByteBuffer.allocate(100);
java nio剖析        
//向缓冲区写入0到100的字节制
java nio剖析
        for(int i = 0; i <100; i++){
java nio剖析            
byte b = (byte) (Math.random() * 100);
java nio剖析            bb.put(b);
java nio剖析        }

java nio剖析        
java nio剖析        System.out.println(
"写入文件前的缓冲区数据");
java nio剖析        bb.flip();
java nio剖析        
while(bb.hasRemaining())
java nio剖析            System.out.print(bb.get() 
+ " ");
java nio剖析        System.out.println();
java nio剖析        
java nio剖析        
//获取一个关联到文件buffer.txt的信道
java nio剖析
        FileChannel fc = new FileOutputStream("buffer.txt").getChannel();
java nio剖析        
//将缓冲区数据写到文件中
java nio剖析
        bb.flip();
java nio剖析        fc.write(bb);
java nio剖析        
//防止缓存
java nio剖析
        fc.force(true);
java nio剖析        
//关闭信道
java nio剖析
        fc.close();
java nio剖析        bb 
= null;
java nio剖析        fc 
= null;
java nio剖析        
java nio剖析        
//下面从文件中读取数据
java nio剖析
        fc = new FileInputStream("buffer.txt").getChannel();
java nio剖析        ByteBuffer bb2 
= ByteBuffer.allocate((int) fc.size());
java nio剖析        fc.read(bb2);
java nio剖析        System.out.println(
"从文件读取的缓冲区数据");
java nio剖析        bb2.flip();
java nio剖析        
while(bb2.hasRemaining())
java nio剖析            System.out.print(bb2.get() 
+ " ");
java nio剖析        System.out.println();
java nio剖析        fc.close();
java nio剖析        bb2 
= null;
java nio剖析        fc 
= null;
java nio剖析        
java nio剖析
java nio剖析    }

java nio剖析
java nio剖析}

java nio剖析
         3.视图缓冲区
         上面我们的缓冲区都是基于字节的,像IntBuffer、LongBuffer等这些都可以调用ByteBuffer的
         as***Buffer(***表示某个数据类型)得到,所以这种类型的缓冲区又被称为视图缓冲区(View Buffer),
       视图缓冲区有以下特点:
a.     视图缓冲区有自己独立的position和limit,但它不是一个新的创建,只是原来字节缓冲区的一个逻辑缓冲区,字节缓冲区的任何修改都会影响视图缓冲区,反之亦然。
b.      视图缓冲区按照数据类型的大小进行索引,而不是字节顺序。
c.       也提供了put()和get()及其系列方法,用于数据的整块传输。
       下面这个例子演示了视图缓冲区:

java nio剖析 package  nio;
java nio剖析
java nio剖析
import  java.io.FileInputStream;
java nio剖析
import  java.nio.ByteBuffer;
java nio剖析
import  java.nio.IntBuffer;
java nio剖析
import  java.nio.channels.FileChannel;
java nio剖析
java nio剖析
public   class  ViewBufferDemo  {
java nio剖析
java nio剖析    
public static void main(String[] args) throws Exception{
java nio剖析        
java nio剖析        
//将文件内容读到缓冲区中
java nio剖析
        FileChannel fc = new FileInputStream("buffer.txt").getChannel();
java nio剖析        ByteBuffer bb 
= ByteBuffer.allocate((int) fc.size());
java nio剖析        fc.read(bb);
java nio剖析        fc.close();
java nio剖析        fc 
= null;
java nio剖析        
java nio剖析        System.out.println(
"从文件读取的字节缓冲区数据");
java nio剖析        bb.flip();
java nio剖析        
while(bb.hasRemaining())
java nio剖析            System.out.print(bb.get() 
+ " ");
java nio剖析        System.out.println();
java nio剖析        
java nio剖析        
//获取视图缓冲区
java nio剖析
        bb.flip();
java nio剖析        IntBuffer ib 
= bb.asIntBuffer();
java nio剖析        System.out.println(
"将字节缓冲区作为整形缓冲区的数据");
java nio剖析        
while(ib.hasRemaining())
java nio剖析            System.out.print(ib.get() 
+ " ");
java nio剖析        System.out.println();
java nio剖析        
java nio剖析        bb 
= null;
java nio剖析        ib 
= null;
java nio剖析        
java nio剖析    }

java nio剖析
java nio剖析}

java nio剖析
       4.映射内存缓冲区
         调用信道的map()方法后,即可将文件的某一部分或全部映射到内存中,映射内存缓冲区是一
         个直接缓冲区,继承自ByteBuffer,但相对于ByteBuffer,它有更多的优点:
a.     内存映射I/O是对信道/缓冲区技术的改进。 当传输大量的数据时,内存映射I/O
速度相对较快,这是因为它使用虚拟内存把文件传输到进程的地址空间中。
b.      映射内存也成为共享内存,因此可以用于相关进程(均映射同一文件)之间的整块数据
传输,这些进程甚至可以不必位于同一系统上,只要每个都可以访问同一文件即可。
c.       当对FileChannel执行映射操作,把文件映射到内存中时,得到的是一个连接到文件的
映射的字节缓冲区,这种映射的结果是,当输出缓冲区的内容时,数据将出现在文件中,
当读入缓冲区时,相当于得到文件中的数据。
        下面这个例子演示了映射内存:

java nio剖析 package  nio;
java nio剖析
java nio剖析
import  java.io.FileInputStream;
java nio剖析
import  java.io.FileOutputStream;
java nio剖析
import  java.nio.MappedByteBuffer;
java nio剖析
import  java.nio.channels.FileChannel;
java nio剖析
java nio剖析
public   class  CopyFile  {
java nio剖析
java nio剖析    
public static void main(String[] args) throws Exception {
java nio剖析
java nio剖析        FileChannel fIChan, fOChan;
java nio剖析        MappedByteBuffer mBuf;
java nio剖析
java nio剖析        fIChan 
= new FileInputStream("buffer.txt").getChannel();
java nio剖析        fOChan 
= new FileOutputStream("bufferTemp.txt").getChannel();
java nio剖析
java nio剖析        mBuf 
= fIChan.map(FileChannel.MapMode.READ_ONLY, 0, fIChan.size());
java nio剖析
java nio剖析        fOChan.write(mBuf);
java nio剖析
java nio剖析        fIChan.close();
java nio剖析        fOChan.close();
java nio剖析        
java nio剖析        fIChan 
= null;
java nio剖析        fOChan 
= null;
java nio剖析        mBuf 
= null;
java nio剖析
java nio剖析    }

java nio剖析
java nio剖析}

java nio剖析

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100528.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 临时重定向和永久重定向的状态码_java重定向怎么写

    临时重定向和永久重定向的状态码_java重定向怎么写重定向重定向分为永久重定向和临时重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面。

  • HttpCanary下载_HTML自我介绍

    HttpCanary下载_HTML自我介绍前言首先,我们无论学习哪个框架,都要带着问题,带着思考去学习思考1:HttpRunner是什么?思考2:HttpRunner的设计模式是什么?思考3:为什么我们要学习HttpRunner?他的

  • MySQL 将字符串转换为数字类型并进行排序

    MySQL 将字符串转换为数字类型并进行排序起因:需要对接第三方统计系统,并且第三方系统给的数据那真的是一团乱,害,都是泪呀,头发又感觉凉飕飕的;数据有毒,所有的小数都是用varchar(20)保存的,现在有要对数据进行排序并展示。示例数据:area_gdp表idareagdp1北京12002上海61003广州60004深圳980select*fromarea_gdpORDERBYgdpASC#查询结果如下1 北京 12003 广州 60002 上海

  • Swift 学习Using Swift mix and match, network: 写rss读者

    Swift 学习Using Swift mix and match, network: 写rss读者

  • SHFileOperation删除文件夹

    SHFileOperation删除文件夹UsesShellapi;varFileOp:TSHFileOpStruct;beginwithFileOpdobeginWnd:=Handle;//hinstance;wFunc:=FO_DELETE;//FO_COPY,FO_RENAME,FO_MOVE,FO_DELETEpFrom:=Pchar(‘D…

  • XSS(跨站脚本攻击)相关内容总结整理

    XSS的攻击相关资料整理文章目录XSS的攻击相关资料整理跨站脚本攻击(XSS)XSS 简介XSS 危害XSS 原理XSS 分类XSS 防御总结XSS 问答参考资料跨站脚本攻击(XSS)XSS 简介人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为XSS。跨站脚本攻击(XSS),是最普遍的Web应用安全漏洞。这类漏洞能够使得攻击者嵌入恶意脚本代码到正常用户

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号