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. C# url信息获取

    假设当前页完整地址是:http://www.360jht.com/game/bbb.aspx?id=5&name=kelli "http://"是协议名 "www ...

  2. Openstack-Ceilometer-SNMP的使用

    1. 物理服务器配置 1.1安装 #yum install -y net-snmp net-snmp-utils 1.2      配置 复制[附件]中snmpd.conf文件到/etc/snmp/目 ...

  3. 【读书笔记《Android游戏编程之从零开始》】4.Android 游戏开发常用的系统控件(EditText、CheckBox、Radiobutton)

    3.4 EditText EditText类官方文档地址:http://developer.android.com/reference/android/widget/EditText.html Edi ...

  4. mysql 防止update/delete误操作

    身为一php开发攻城狮,常常涉及在应用中写update/delete语句,忘记加where,后果不堪设想. 还会出现在cml下直接操作mysql的情况,如果mysql 权限够大,一个update/de ...

  5. Appium路线图及1.0正式版发布

    Appium更新的速度极快,从我试用时候的0.12到1.0(0.18版本后就是1.0),完全符合移动互联网的节奏. 更新可能会慢,可以多试几次 整理了testerhome上思寒发表的帖子,让我们来看下 ...

  6. Medial Queries的另一用法:实现IE hack的方法

    所谓Medial Queries就是媒体查询. 随着Responsive设计的流行,Medial Queries可算是越来越让人观注了.他可以让Web前端工程实现不同设备下的样式选择,让站点在不同的设 ...

  7. JSP中文乱码问题《转》

    之前总是碰到JSP页面乱码的问题,每次都是现在网上搜,然后胡乱改,改完也不明白原因. 这次正好作下总结,中文乱码就是因为编码不符,可能出现乱码有四个地方: 1 JSP编码乱码 2 HTML编码乱码 3 ...

  8. 只有图片拼接的html页面图片之间有白条的解决方法

    有时候会有这样的页面,整个页面也就是几张切好的图片组成,但是把这些图片使用代码拼接好,又总会出现图片间有白条的问题,如下图: 解决方法:给图片的父容器添加 line-height: 0; 就好了,因为 ...

  9. cotangent Laplacian

    几何网格处理经常用到 cotangent laplacian矩阵.前几天把这个功能整合到我的Maya 转 Matlab插件了. 这里发一个利用cotangent laplacian计算特征向量并显示的 ...

  10. C# WinForm 中Console 重定向输出到ListBox控件中显示

                        {              VoidAction action =              {                  lstBox.Items. ...