1、IO与NIO


  IO就是普通的IO,或者说原生的IO。特点:阻塞式、内部无缓冲,面向流。

  NIO就是NEW IO,比原生的IO要高效。特点:非阻塞、内部有缓存,面向缓冲。

  要实现高效的IO操作,尤其是服务器端程序时,需要使用NIO进行开发。

2、NIO的理解


  NIO就是中引入了通道和缓冲器的概念。我们可以把文件想想成一个水池,以前是我们使用普通IO时是直接从池中取水。现在的NIO就相当于在水池中引出来一个水管,并将水管的另一端放在一个跟小的蓄水池中。当我们需要水时直接从蓄水池中取水。NIO中蓄水池就是Buffer类,我们可以设置这个类的大小,而这个蓄水池也只能放基本数据类型。而所谓的水管就是Channel了。

 具体buffer类:

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

 具体的channel类

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

2、NIO的使用


1.buffer的三大属性

  • capacity  缓冲区的最大容量
  • limit  读写的限制,比如读的时候缓冲区就只有5个字节,那么limit就等于4。当写缓冲区时,limit一般指向缓冲区的末尾
  • position   当前读写的位置
package com.dy.xidian;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; public class GetChannel {
public static final int BSIZE = 1024;
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
FileChannel fc = new FileOutputStream("E:/html/utf-8.php").getChannel();
// 将传入的数组作为ByteBuffer的储存器,就是所谓的缓冲区
fc.write(ByteBuffer.wrap("some text".getBytes()));
fc.close();
fc = new RandomAccessFile("E:/html/utf-8.php", "rw").getChannel();
// 通过position更改管道的位置,我们可以认为水池中水管的位置是不固定
fc.position(fc.size());
fc.write(ByteBuffer.wrap("Some more".getBytes()));
fc.close();
fc = new FileInputStream("E:/html/utf-8.php").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff);
     // 重置缓冲区,令limit=position,position=0,read之后必须的操作
buff.flip();
while (buff.hasRemaining())
System.out.println((char) buff.get());
}
}

2.文件copy


package com.dy.xidian;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; public class FileCopy {
public static final int BSIZE = 1024;
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel in = new FileInputStream(args[0]).getChannel();
FileChannel out = new FileOutputStream(args[1]).getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
while (in.read(buffer) != -1) {
//limit=position, position=0
buffer.flip();
out.write(buffer);
//position=0,limit=capacity
buffer.clear();
}
}
}

改进:将两个管道直接连接起来

package com.dy.xidian;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel; public class GetChannel {
public static final int BSIZE = 1024;
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel in = new FileInputStream(args[0]).getChannel();
FileChannel out = new FileOutputStream(args[1]).getChannel();
     //0:源文件的起始位置,in.size():数据量,out目的文件
in.transferTo(0, in.size(), out);
}
}

3.转换数据

package com.dy.xidian;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset; public class BufferToText {
private static final int BSIZE = 1024; @SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
/************** 写操作 ****************/
FileChannel fc = new FileOutputStream("data2.txt").getChannel();
// ByteBuffer为字节缓冲器,我们向缓冲器中输入数据时应对其进行编码
// 从缓冲器中读数据时应该进行解码
fc.write(ByteBuffer.wrap("Some text".getBytes("utf-8")));
fc.close();
/************** 读操作 ****************/
fc = new FileInputStream("data2.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff);
buff.flip();
System.out.println(buff.asCharBuffer());
// position=0
buff.rewind();
//设置字符集,解决乱码问题
String encoding = System.getProperty("file.encoding");
System.out.println("Decoded using " + encoding + ": "
+ Charset.forName(encoding).decode(buff));
//通过charBuffer向ByteBuffer中写入
fc = new FileOutputStream("data2.txt").getChannel();
buff = ByteBuffer.allocate(24);
buff.asCharBuffer().put("Some text");
fc.write(buff);
fc.close();
fc = new FileInputStream("data2.txt").getChannel();
buff.clear();
fc.read(buff);
buff.flip();
System.out.println(buff.asCharBuffer());
}
}

4.获取基本数据类型

package com.dy.xidian;

import java.nio.ByteBuffer;

public class GetData {
private static final int BSIZE = 1024;
public static void main(String[] args) {
ByteBuffer bb = ByteBuffer.allocate(BSIZE);
int i = 0;
// 缓冲区自动被初始化为0
while (i++ < bb.limit())
// limit不变,position++
if (bb.get() != 0)
System.out.println("nonzero!");
System.out.println("i = " + i);
// position = 0
bb.rewind();
/* 以字符的方式向缓冲区写 */
bb.asCharBuffer().put("Howdy");
char c;
while ((c = bb.getChar()) != 0)
System.out.print(c + " ");
System.out.println("");
bb.rewind();
/* 以short类型向缓冲区写 */
bb.asShortBuffer().put((short) 471);
System.out.println(bb.getShort());
bb.rewind();
/* 以int类型向缓冲区写 */
bb.asIntBuffer().put(99471142);
System.out.println(bb.getInt());
bb.rewind();
/* 以long类型向缓冲区写 */
bb.asLongBuffer().put(99471142);
System.out.println(bb.getLong());
bb.rewind();
/* 以float类型向缓冲区写 */
bb.asFloatBuffer().put(99471142);
System.out.println(bb.getFloat());
bb.rewind();
/* 以double类型向缓冲区写 */
bb.asDoubleBuffer().put(99471142);
System.out.println(bb.getDouble());
bb.rewind();
}
}

代码中使用到了视图缓冲器(asIntBuffer、asFloatBuffer...),通过视图缓冲器来操作底层的ByteBuffer使得编程更加方便。不同的视图缓冲器对底层数组的影响是不同的,比如char视图会一次读两个字节,position则会移动两位,这点需要注意。ByteBuffer是以大端(低地址存高数据位)的方式存储数据。

4.相邻字符交换

package com.dy.xidian;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer; public class Exchange {
public static void main(String[] args) throws UnsupportedEncodingException {
char[] data = "usingbuffers".toCharArray();
System.out.println("char[] data = " + data.length);
ByteBuffer bb = ByteBuffer.allocate(data.length * 2);
System.out.println("bytebuffer.capacity = " + bb.capacity());
System.out.println("bytebuffer.limit = " + bb.limit());
CharBuffer cb = bb.asCharBuffer();
cb.put(data);
System.out.println("charBuffer.limit = " + cb.limit());
char c1, c2;
cb.rewind();
while (cb.hasRemaining()) {
cb.mark();
c1 = cb.get();
c2 = cb.get();
cb.reset();
cb.put(c2).put(c1);
}
cb.rewind();
System.out.println(cb);
}
}

3、参考文章


http://www.iteye.com/magazines/132-Java-NIO#579

http://blog.csdn.net/linxcool/article/details/7771952

http://blog.csdn.net/baple/article/details/12749005

http://www.cnblogs.com/mjorcen/p/3992245.html

JAVA中的NIO(一)的更多相关文章

  1. Java中的NIO基础知识

    上一篇介绍了五种NIO模型,本篇将介绍Java中的NIO类库,为学习netty做好铺垫 Java NIO 由3个核心组成,分别是Channels,Buffers,Selectors.本文主要介绍着三个 ...

  2. JAVA中的NIO (New IO)

    简介 标准的IO是基于字节流和字符流进行操作的,而JAVA中的NIO是基于Channel和Buffer进行操作的. 传统IO graph TB; 字节流 --> InputStream; 字节流 ...

  3. java中的NIO和IO到底是什么区别?20个问题告诉你答案

    摘要:NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多. 本文分享自华为云社区<jav ...

  4. Java中的NIO和IO的对比分析

    总的来说,java中的IO和NIO主要有三点区别: IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器(Selectors) 1.面向流与面向缓冲 Java NIO和IO之间第一个最大的 ...

  5. Java中的NIO及IO

    1.概述 Java NIO(New IO) 是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同, ...

  6. JAVA中的NIO(二)

    一.内存文件映射 内存文件映射允许我们创建和修改那些因为太大而不能放入内存中的文件.有了内存文件映射,我们就可以假定整个文件都在内存中,而且可以完全把文件当作数组来访问. package com.dy ...

  7. JAVA 中BIO,NIO,AIO的理解

    [转自]http://qindongliang.iteye.com/blog/2018539 ?????????????????????在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解 ...

  8. JAVA 中BIO,NIO,AIO的理解以及 同步 异步 阻塞 非阻塞

    在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步 ...

  9. JAVA 中BIO,NIO,AIO的理解 (转)

    转自: http://qindongliang.iteye.com/blog/2018539 另外类似可参考资料 :http://www.360doc.com/content/13/1029/20/9 ...

随机推荐

  1. Linux系统命令查询软件包

    转载自:http://blog.chinaunix.net/uid-346158-id-2131252.html,http://www.jb51.net/os/RedHat/1102.html, 一. ...

  2. android:layout_gravity和android:gravity的区别

    1.首先来看看android:layout_gravity和android:gravity的使用区别. android:gravity: 这个是针对控件里的元素来说的,用来控制元素在该控件里的显示位置 ...

  3. APP 接口开发及读取静态缓存

    <?php /** * Description: App 接口 * Create date:2015-10-19 13:36 * Author: zhaoyingnan **/ class Re ...

  4. HTML5与触摸界面

    习惯了开发典型的面向电脑端浏览器的网站在开发手机端网站或者移动App的时候面对很多新的问题,这些新的问题,在我看来或多或少会给浏览者在使用网站或App的时候带来不好的用户体验,对于一个产品级应用,用户 ...

  5. ant+jenkins+testng+selenium集成环境搭建

    一.前序工作 下载ant:http://ant.apache.org/bindownload.cgi 下载jenkins:http://jenkins-ci.org/ 下载testng:http:// ...

  6. 【Ext.Net学习笔记】04:Ext.Net中使用数据、Ext.Net Store的用法、Ext.Net ComboBox用法

    之前的几篇文章都是介绍Ext.Net较为基础的东西,今天的这一篇将介绍数据的一些用法,包括XTemplate绑定数据.Store(Modal.Proxy).ComboBox的用法等. XTemplat ...

  7. 第11章 Windows线程池(1)_传统的Windows线程池

    第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...

  8. mysql乱码的好文

    1. http://www.blogjava.net/wldandan/archive/2007/09/04/142669.html 2. http://www.111cn.net/database/ ...

  9. iOS获取窗口当前显示的控制器

    解决类似网易新闻客户端收到新闻推送后,弹出一个UIAlert,然后跳转到新闻详情页面这种需求 1.提供一个UIView的分类方法,这个方法通过响应者链条获取view所在的控制器 - (UIViewCo ...

  10. 区块链技术(一):Truffle开发入门

    以太坊是区块链开发领域最好的编程平台,而truffle是以太坊(Ethereum)最受欢迎的一个开发框架,这是我们第一篇区块链技术文章介绍truffle的原因,实战是最重要的事情,这篇文章不讲原理,只 ...