io和nio的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了io和nio的区别相关的知识,希望对你有一定的参考价值。

什么是通道Channel(通道)
顾名思义,就是通向什么的道路,为某个提供了渠道。在传统IO中,我们要读取一个文件中的内容,通常是像下面这样读取的:

public static void copy_1(){
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("c:\timg.jpg");
out = new FileOutputStream("D:\timg.jpg");
int ch = 0;
while((ch=in.read())!=-1){//这个方法是对这个流一个一个字节的读,返回的int就是这个字节的int表示方式
out.write(ch);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
    if(out!=null){
        out.close();
    }
} catch (IOException e) {
    e.printStackTrace();
}
try {
    if(in!=null){
        in.close();
    }
} catch (Exception e2) {
    e2.printStackTrace();
}
}
}
public static void copy_2(){
FileInputStream in = null;
FileOutputStream out = null;
try {
in=new FileInputStream("c:\timg.jpg");
out=new FileOutputStream("d:\timg.jpg");
byte[] buffer = new byte[1024];
int len = 0;
while((len=in.read(buffer))!=-1){//这个方法是先规定一个数组长度,将这个流中的字节缓冲到数组b中,返回的这个数组中的字节个数,这个缓冲区没有满的话,则返回真实的字节个数,到未尾时都返回-1
out.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null){
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(in!=null){
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}

这里的InputStream实际上就是为读取文件提供一个通道的。

  因此可以将NIO 中的Channel同传统IO中的Stream来类比,但是要注意,传统IO中,Stream是单向的,比如InputStream只能进行读取操作,OutputStream只能进行写操作。而Channel是双向的,既可用来进行读操作,又可用来进行写操作。
以下是常用的几种通道:

FileChannel

SocketChanel

ServerSocketChannel

DatagramChannel

通过使用FileChannel可以从文件读或者向文件写入数据;通过SocketChannel,以TCP来向网络连接的两端读写数据;通过ServerSocketChanel能够监听客户端发起的TCP连接,并为每个TCP连接创建一个新的SocketChannel来进行数据读写;通过DatagramChannel,以UDP协议来向网络连接的两端读写数据。

public class Test {

public static void main(String[] args) throws IOException  {

    File file = new File("data.txt");

    FileOutputStream outputStream = new FileOutputStream(file);

    FileChannel channel = outputStream.getChannel();

    ByteBuffer buffer = ByteBuffer.allocate(1024);

    String string = "java nio";

    buffer.put(string.getBytes());

    buffer.flip();     //此处必须要调用buffer的flip方法

    channel.write(buffer);

    channel.close();

    outputStream.close();

}  
    }

通过上面的程序会向工程目录下的data.txt文件写入字符串"java nio",注意在调用channel的write方法之前必须调用buffer的flip方法,否则无法正确写入内容

什么是缓冲区Buffer(缓冲区)
 Buffer,故名思意,缓冲区,实际上是一个容器,是一个连续数组。Channel提供从文件、网络读取数据的渠道,但是读取或写入的数据都必须经由Buffer。
在NIO中,Buffer是一个顶层父类,它是一个抽象类,常用的Buffer的子类有:

ByteBuffer

IntBuffer

CharBuffer

LongBuffer

DoubleBuffer

FloatBuffer

ShortBuffer

  如果是对于文件读写,上面几种Buffer都可能会用到。但是对于网络读写来说,用的最多的是ByteBuffer

什么是选择器Selector(选择器)
Selector运行单线程处理多个Channel,如果你的应用打开了多个通道,但每个连接的流量都很低,使用Selector就会很方便。例如在一个聊天服务器中。要使用Selector, 得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新的连接进来、数据接收等。

io和nio的区别
IO是面向流的,NIO是面向缓冲的;
IO是阻塞的,NIO是非阻塞的;
IO是单线程的,NIO 是通过选择器来模拟多线程的;

以上是关于io和nio的区别的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO和IO的区别

java nio 与io区别

Java NIO与IO的区别和比较

Java NIO:IO与NIO的区别

IO与NIO的区别

Java NIO:IO与NIO的区别