博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA NIO中的Channels和Buffers
阅读量:6174 次
发布时间:2019-06-21

本文共 4337 字,大约阅读时间需要 14 分钟。

前言

Channels和Buffers是JAVA NIO里面比较重要的两个概念,NIO正是基于Channels和Buffers进行数据操作,且数据总是从Channels读取到Buffers,或者从Buffers写入到Channels

通道(Channel)

NIO中的通道与IO中的流类似,不过流是单向的,而通道是双向的。例如InputStream、OutputStream等都是单向的,一个流只能进行读数据或写数据;而FileChannel、SocketChannel等是双向的,既可以从中读数据,也可以写数据。

通道与流的区别如下:

  • 通道是双向的,可读可写,而流是单向的,只能读或只能写;
  • 通道中的数据是跟Buffer进行交互的,但在面向流的I/O中,数据是直接读/写到流中的;
  • NIO可以异步读写数据;

以FileChannel为例,如下:

FileChannel

FileChannel是文件写入/读取相关的通道;

产生FileChannel的方式:

  • 从FileOutputStream中获取;
  • 从RandomAccessFile中获取;
  • 从FileInputStream中获取;

下面举个例子,分别从FileOutputStream、RandomAccessFile、FileInputStream中获取文件通道,进行相关写入/读取操作;

package com.pichen.io;import java.nio.*;import java.nio.channels.*;import java.io.*;public class GetChannel {    private static final int BSIZE = 1024;    public static void main(String[] args) throws Exception {        // 创建文件输出字节流        FileOutputStream fos = new FileOutputStream("data.txt");        //得到文件通道        FileChannel fc = fos.getChannel();        //往通道写入ByteBuffer        fc.write(ByteBuffer.wrap("Some text ".getBytes()));        //关闭流        fos.close();        //随机访问文件        RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");        //得到文件通道        fc = raf.getChannel();        //设置通道的文件位置 为末尾        fc.position(fc.size());         //往通道写入ByteBuffer        fc.write(ByteBuffer.wrap("Some more".getBytes()));        //关闭        raf.close();                //创建文件输入流        FileInputStream fs = new FileInputStream("data.txt");        //得到文件通道        fc = fs.getChannel();        //分配ByteBuffer空间大小        ByteBuffer buff = ByteBuffer.allocate(BSIZE);        //从通道中读取ByteBuffer        fc.read(buff);        //调用此方法为一系列通道写入或相对获取 操作做好准备        buff.flip();        //从ByteBuffer从依次读取字节并打印        while (buff.hasRemaining()){            System.out.print((char) buff.get());        }        fs.close();    }}

再举个文件复制的例子,有两种方式:

  • 打开一个FileChannel用于读,另一个用于写;
  • 直接调用transferTo或者transferFrom方法传输通道之间的数据;

如下代码示例:

package com.pichen.io;import java.nio.*;import java.nio.channels.*;import java.io.*;public class ChannelCopy {    private static final int BSIZE = 1024;    public static void main(String[] args) throws Exception {        //获取文件输入输出字节流        FileInputStream fis = new FileInputStream("C:\\test.jpg");        FileOutputStream fos = new FileOutputStream("C:\\test_copy.jpg");                //从文件输入输出字节流中获取通道        FileChannel fci = fis.getChannel();        FileChannel fco = fos.getChannel();        //分配ByteBuffer空间大小        ByteBuffer buffer = ByteBuffer.allocate(BSIZE);                //第一种种数据拷贝方式,直接往输入通道写数据        while (fci.read(buffer) != -1) {            //为写入操作做准备            buffer.flip();             //往输出通道写入buffer            fco.write(buffer);            //清空buffer,重置内部指针            buffer.clear();         }                //第二种数据拷贝方式,利用transferTo或者transferFrom方式        FileOutputStream fos2 = new FileOutputStream("C:\\test_copy2.jpg");        FileChannel fco2 = fos.getChannel();        fci.transferTo(0, fci.size(), fco2);                        fis.close();        fos.close();        fos2.close();    }}

缓冲区(Buffer)

buffer用于与通道进行交互,举个例子如下,这里以ByteBuffer为例;

package com.pichen.io;import java.nio.*;import java.nio.channels.*; import java.io.*; public class GetChannel { private static final int BSIZE = 1024; public static void main(String[] args) throws Exception { // 随机访问文件 RandomAccessFile raf = new RandomAccessFile("C:\\data.txt", "rw"); // 得到文件通道 FileChannel fc = raf.getChannel(); ByteBuffer bf = ByteBuffer.allocate(BSIZE); int bytesRead = fc.read(bf); // read into buffer. while (bytesRead != -1) { // 通过flip()方法将Buffer从写模式切换到读模式 bf.flip(); while (bf.hasRemaining()) { // 每次读取一个字节 System.out.print((char) bf.get()); } // 清空缓存,准备往缓存写数据 bf.clear(); bytesRead = fc.read(bf); } // 关闭 raf.close(); } }

Buffer基本方法

  • flip方法:从buffer读数据之前调用,从写模式切换到读模式;
  • clear:往buffer写数据之前调用,全部清除;
  • compact:往buffer写数据之前调用,只清除已读取的数据,新写入的数据会添加到未读数据末尾;

Buffer基本属性

  • capacity:buffer空间大小;
  • position:读写数据时的指针,指向当前位置;
  • limit:读数据时,表示当前可读数据的大小;写数据时,即buffer大小=capacity;

Buffer的类型

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

Buffer中写数据

  • 从Channel写到Buffer,调用通道的read(Buffer buffer)方法
  • put()方法写到Buffer里,调用Buffer的put方法

Buffer中读取数据

  • 从Buffer读取数据到Channel,调用通道的write(Buffer buffer)方法
  • 使用get()方法从Buffer中读取数据,调用Buffer的get方法

 

参考:http://ifeve.com/java-nio-all/

转载于:https://www.cnblogs.com/chenpi/p/5372786.html

你可能感兴趣的文章
Eric,基于多搜索引擎的自动问答机器人
查看>>
Logstash6.1 手动安装插件
查看>>
这个开场… 太吊胃口了…
查看>>
C#-老生常谈的 值类型与引用类型
查看>>
人工智能GPU/FPGA/ASIC/类脑芯片优势分析
查看>>
linux中断线程化分析【转】
查看>>
Java 基础【05】你的多继承纳?
查看>>
QTP的那些事--操作excel的方法总结(可用)
查看>>
VC++线程通信
查看>>
bat薪酬
查看>>
ORACLE SQL:经典查询练手第一篇
查看>>
SQL Server高可用性(High Availability)——Log Shipping
查看>>
Java中HashMap案例
查看>>
ICE专题:网络服务平台比较
查看>>
Dsicuz x2.5、X3、X3.2如何去掉域名后面的/forum.php
查看>>
java.util.zip.DataFormatException: invalid distance too far back
查看>>
iml文件
查看>>
[汇编] 2数相加极简单版
查看>>
oracle登录错误:ORA-28000: the account is locked 解决方法
查看>>
VS调试Tip集结
查看>>