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 ...
随机推荐
- OpenGL 学习笔记 01 环境配置
以下教程仅适用于Mac下的Xcode编程环境!其他的我也不会搞. 推荐教程:opengl-tutorial 本项目Github网址 OpenGL太可怕了...必需得把学的记下来,不然绝壁 ...
- Java Consumer and Producer demo
import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; class producer { Rando ...
- fdtd simulation, plotting with gnuplot, writting in perl
# 9月13日 于成都黄龙溪 1 #!/usr/bin/perl # Author : Leon Email: yangli0534@gmail.com # fdtd simulation , plo ...
- 怎样用ZBrush雕刻人体造型
之前我们通过学习使用ZBrush®中的Curves和Insert笔刷快速创建模型的躯干.四肢以及手指.经过老师耐心的讲解我们也收获了很多,知道了创建模型的流程和雕刻技巧.今天的ZBrush教程我们将结 ...
- T-SQL 语句创建Database的SQL mirroring关系
1 证书部分:principle 和 secondary 端执行同样操作,更改相应name即可 USE master; --1.1 Create the database Master Key, if ...
- hdu-5920 Ugly Problem(贪心+高精度)
题目链接: Ugly Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- JavaWeb学习----JSTL标签库
一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Co ...
- 贴图在Unity中的设置
例如:一张512X512的图片占用的内存大小,计算方法:512*512*4/1024=1.024MB. 如果在贴图设置里设置成真彩色那就等于计算的值,设置成16位色彩,内存占用会减少. 在进行性能优化 ...
- android:ToolBar详解(手把手教程)
今年(2014) 的 google i/o 发表令多数人为之一亮的 material design,而 google 也从「google i/o 2014」 开始,大家也陆陆续续地看到其更新的 and ...
- css3高级运动keyframes
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...