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 ...
随机推荐
- JavaScript中点号“.”的多义性
点号「.」在JavaScript中有两种语义 语义1.表示算术中的小数点(浮点数),如 2.5 语义2.取对象属性.方法,如 [].push(2) 这几乎没有任何难理解的地方,但下面这个问题则很有趣. ...
- (三)openwrt主Makefile解析
本周成胖子每周一博到了第四周^_^ 前言 主Makefile结构 顶层 第二层 尾记 前言 前一篇,我们大概描述了整个镜像文件的生成过程.本周我们来解析主Makefile,看看主要编译过程是怎么产生的 ...
- vs安装mvc
需要一个MVC框架和SP1补丁包,SP1补丁包的下载地址为:http://www.microsoft.com/downloads/details.aspx?FamilyID=27673c47-b3b5 ...
- FileInputFormat
MapReduce框架要处理数据的文件类型 FileInputFormat这个类决定. TextInputFormat是框架默认的文件类型,可以处理Text文件类型,如果你要处理的文件类型不是Text ...
- MFC双缓冲绘图实例
本人之前一直了解双缓冲绘图的基本原理,但是在研究很久之后才大概知道具体的使用过程,本文将详细介绍本人在实际项目中使用双缓冲绘图的案例. 实现功能:主界面显示某张包含人脸的图片,通过dlib detec ...
- 二分法 organ Saltless
organ [描述] 现在某组织中(记作R)有n个人,他们的联络网形成一棵以Saltless为根的树,有边相连代表两人可以直接联络. 每个人有一个代号,Saltless代号为1,且除Saltless外 ...
- 算法最坏,平均和最佳情况(Worst, Average and Best Cases)-------geeksforgeeks 翻译
最坏,平均和最佳运行时间(Worst, Average and Best Cases) 在上一篇文章中,我们讨论到了渐进分析可以解决分析算法的问题,那么在这一篇中,我们用线性搜索来举例说明一下如何用渐 ...
- 3xian之所在(转)
最后一天,漫天飘起了雪花,假装欢送我离去. 这次WF之战不太顺利,早期的C题大概花了1秒钟构思,然而由于输出格式多了一个空格直到两个半小时才逃脱Wrong Answer的纠缠.还好lynncui在期间 ...
- map学习笔记
collection是单列集合,map是双列集合.其中包含<k,v>键值对,注意:键具有唯一性,而值不唯一. 在此列举三个读取方式:keyset,valueset,及entryset. k ...
- AC日记——津津的储蓄计划 P1089 (水!)
题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里 ...