JAVA中的NIO(一)
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(一)的更多相关文章
- Java中的NIO基础知识
上一篇介绍了五种NIO模型,本篇将介绍Java中的NIO类库,为学习netty做好铺垫 Java NIO 由3个核心组成,分别是Channels,Buffers,Selectors.本文主要介绍着三个 ...
- JAVA中的NIO (New IO)
简介 标准的IO是基于字节流和字符流进行操作的,而JAVA中的NIO是基于Channel和Buffer进行操作的. 传统IO graph TB; 字节流 --> InputStream; 字节流 ...
- java中的NIO和IO到底是什么区别?20个问题告诉你答案
摘要:NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多. 本文分享自华为云社区<jav ...
- Java中的NIO和IO的对比分析
总的来说,java中的IO和NIO主要有三点区别: IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器(Selectors) 1.面向流与面向缓冲 Java NIO和IO之间第一个最大的 ...
- Java中的NIO及IO
1.概述 Java NIO(New IO) 是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同, ...
- JAVA中的NIO(二)
一.内存文件映射 内存文件映射允许我们创建和修改那些因为太大而不能放入内存中的文件.有了内存文件映射,我们就可以假定整个文件都在内存中,而且可以完全把文件当作数组来访问. package com.dy ...
- JAVA 中BIO,NIO,AIO的理解
[转自]http://qindongliang.iteye.com/blog/2018539 ?????????????????????在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解 ...
- JAVA 中BIO,NIO,AIO的理解以及 同步 异步 阻塞 非阻塞
在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步 ...
- JAVA 中BIO,NIO,AIO的理解 (转)
转自: http://qindongliang.iteye.com/blog/2018539 另外类似可参考资料 :http://www.360doc.com/content/13/1029/20/9 ...
随机推荐
- Go
一.简介 https://zh.wikipedia.org/wiki/Go 二.安装 1)低版本 http://blog.sina.com.cn/s/blog_59cc90640102xm8r.htm ...
- mysql sql获取上条插入id,update影响行数
1.获取上条插入数据 LAST_INSERT_ID(); 2.获取update影响行数. ROW_COUNT(); mysql> UPDATE t -> SET address = 'be ...
- 图片代替radio
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- 迅为4412开发板支持AVIN视频输入/AV监控摄像头输入模块
AVIN模块(iTOP-4412开发板专用) 产品介绍:视频输入/AV监控摄像头输入模块: 该模块及配套的软件为开发视频采集.监控.车载后视等产品提供了很好的参考. iTOP-4412 开发平台 开发 ...
- Mathout
1. 用Maven搭建Mahout的开发环境,并完成PPT 26页,最简单的例子.要求有过程说明和截图. 2. 用案例的数据集,基于Mahout,任选一种算法,对任意一个女性用户进行协同过滤推荐,并解 ...
- MyDiary,《你的名字。》同款日记应用
新海城导演的新作<你的名字.>已经于 12 月 2 日在国内公映,这部评价极高的动画电影无论在剧情还是美术上都相当出色,是一部不容错过的好片.如果你还没有看过,赶快趁着还没下档买票去看看吧 ...
- Django中的syncdb命令
从官方文档的意思来看,现在他已经成为migrate命令的同义词了,和migrate命令有相同的作用. Deprecated since version 1.7: This command has be ...
- mysql创建表
说明:此文件包含了blog数据库中建立所有的表的Mysql语句. 在sql语句中注意“约束的概念": 1.实体完整性约束(主键--唯一且非空) primary key() 违约处理:No a ...
- Android代码优化----Application节点的模板写法及UI工具类
一. MyApplication类的编写: 新建一个类MyApplication,继承自Application.代码如下: MyApplication.java: package com.smyhva ...
- [cb] Unity Editor 添加右键菜单
需求 为Unity的Editor窗口添加右键菜单 实现代码 // This example shows how to create a context menu inside a custom Edi ...