java nio 通道(一)

本文章来自于本人个人博客:java nio 通道(一)

通道用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效的传输数据。

在学习channel以前,先来观察一下channel的家族吧:

一,打开通道

通道分为File I/O和Stream I/O,对应的类分别为FileChannel和 SocketChannel,ServerSocketChannel, DatagramChannel。通道可以用多种方式创建,但是一个FileChannel对象却只能通过在一个打开的RandomAccessFile,FileInputStream和FileOutputStream对象上调用getChannel()方法来获取。

SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",port));
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress("localhost",port));
DatagramChannel dc = Datagram.open();
RandomAccessFile raf = new RandomAccessFile("filepath","r");
FileChannel fc = raf.getChannel();

在使用IO流创建文件通道时,如果RandomAccessFile创建的时候是只读,则通道也是只读,如果设置的是写或者读写模式,则可修改数据。因此,通过FileChannel得到的ByteBuffer也将随着只读而只读,读写而读写。

二,矢量I/O

矢量I/O即Scatter/Gather,scatter的功能是将一个大缓冲区的数据一次性读入几个小的缓冲区中,而gather的功能是将几个小缓冲区的数据一次性读入一个大的缓冲区中,然后沿着通道发送出去。Scatter/Gather应该使用直接的ByteBuffer以从本地I/O获取最大性能优势。

ByteBuffer header = ByteBuffer.allocateDirect(10);
ByteBuffer body = ByteBuffer.allocateDirect(80);
ByteBuffer[] buffers = {header, body};
int bytesRead = channel.read(buffers);

here is a simple example:


通道用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效的传输数据。



在学习channel以前,先来观察一下channel的家族吧:



一,打开通道

通道分为File I/O和Stream I/O,对应的类分别为FileChannel和 SocketChannel,ServerSocketChannel, DatagramChannel。通道可以用多种方式创建,但是一个FileChannel对象却只能通过在一个打开的RandomAccessFile,FileInputStream和FileOutputStream对象上调用getChannel()方法来获取。
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",port));
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress("localhost",port));
DatagramChannel dc = Datagram.open();
RandomAccessFile raf = new RandomAccessFile("filepath","r");
FileChannel fc = raf.getChannel();

在使用IO流创建文件通道时,如果RandomAccessFile创建的时候是只读,则通道也是只读,如果设置的是写或者读写模式,则可修改数据。因此,通过FileChannel得到的ByteBuffer也将随着只读而只读,读写而读写。

二,矢量I/O

矢量I/O即Scatter/Gather,scatter的功能是将一个大缓冲区的数据一次性读入几个小的缓冲区中,而gather的功能是将几个小缓冲区的数据一次性读入一个大的缓冲区中,然后沿着通道发送出去。Scatter/Gather应该使用直接的ByteBuffer以从本地I/O获取最大性能优势。

ByteBuffer header = ByteBuffer.allocateDirect(10);
ByteBuffer body = ByteBuffer.allocateDirect(80);
ByteBuffer[] buffers = {header, body};
int bytesRead = channel.read(buffers);

here is a simple example:

package com;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;

public class TestByteOrder {

    /**
     * 功能:
     * 作者: jiangfuqiang
     * 创建日期:2014-8-3
     * 修改者: mender
     * 修改日期: modifydate
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        File file = new File("/Users/jiang/Desktop/3.txt");
        if(!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(file);
        GatheringByteChannel gbc = fos.getChannel();
        ByteBuffer buffer1 = ByteBuffer.allocateDirect(10);
        buffer1.put((byte)‘j‘);
        buffer1.put((byte)‘i‘);
        buffer1.put((byte)‘a‘);
        buffer1.put((byte)‘n‘);
        buffer1.put((byte)‘g‘);
        buffer1.put((byte)‘j‘);
        buffer1.put((byte)‘i‘);
        buffer1.put((byte)‘a‘);
        buffer1.put((byte)‘n‘);
        buffer1.put((byte)‘\n‘);
        ByteBuffer buffer2 = ByteBuffer.allocateDirect(20);
        buffer2.put((byte)‘j‘);
        buffer2.put((byte)‘i‘);
        buffer2.put((byte)‘a‘);
        buffer2.put((byte)‘n‘);
        buffer2.put((byte)‘g‘);
        buffer2.put((byte)‘f‘);
        buffer2.put((byte)‘u‘);
        buffer2.put((byte)‘h‘);
        buffer2.put((byte)‘x‘);
        buffer2.put((byte)‘n‘);
        buffer2.put((byte)‘j‘);
        buffer2.put((byte)‘i‘);
        buffer2.put((byte)‘a‘);
        buffer2.put((byte)‘n‘);
        buffer2.put((byte)‘g‘);
        buffer2.put((byte)‘f‘);
        buffer2.put((byte)‘u‘);
        buffer2.put((byte)‘h‘);
        buffer2.put((byte)‘x‘);
        buffer2.put((byte)‘\n‘);
        ByteBuffer buffer3 = ByteBuffer.allocateDirect(30);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
        buffer3.put((byte)‘j‘);
//        buffer3.put((byte)‘j‘);
//        buffer3.put((byte)‘j‘);
        //一定要记得在写入以前调用flip方法
        buffer1.flip();
        buffer2.flip();
        buffer3.flip();
        ByteBuffer[] buffers = {buffer1,buffer2,buffer3};
        while(gbc.write(buffers) > 0) {

        }
        gbc.close();

        FileInputStream fis = new FileInputStream(file);
        ScatteringByteChannel sbc = fis.getChannel();
        ByteBuffer b1 = ByteBuffer.allocateDirect(10);
        ByteBuffer b2 = ByteBuffer.allocateDirect(20);
        ByteBuffer b3 = ByteBuffer.allocateDirect(30);
        ByteBuffer[] bs = {b1,b2,b3};
        sbc.read(bs);
        for(ByteBuffer bb : bs) {
            bb.flip();
            //注意,这个数组的初始化一定要放在flip()方法的后面,不然会将所读取的数据截断
            byte[] data = new byte[bb.remaining()];
            while(bb.hasRemaining()) {
                //System.out.println(bb.get());
                bb.get(data);
                if(data.length > 0) {
                    System.out.print(data.length + " data=" + new String(data));
                }
                data = new byte[bb.remaining()];
            }
            bb.clear();
        }
    }

}

下一篇我们将一起来学习文件通道

下一篇我们将一起来学习文件通道

java nio 通道(一)

时间: 2024-11-11 02:53:44

java nio 通道(一)的相关文章

java nio 通道(二)

本文章来源于我的个人博客: java nio 通道(二) 一,文件通道 文件通道总是堵塞式的,因此不能被置于非堵塞模式. FileChannel对象是线程安全的.多个进程能够在同一个实例上并发调用方法而不会引起不论什么问题,只是非全部的操作都是多线程的.影响通道位置或者影响文件大小的操作都是单线程的. 通过FileChannel实例看到的某个文件的视图同通过一个外部的非java进程看到的该文件的视图可能一致也可能不一致. 创建文件通道: RandomAccessFile randomAccess

Java NIO 通道之间的数据传输

在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFrom() FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中(译者注:这个方法在JDK文档中的解释为将字节从给定的可读取字节通道传输到此通道的文件中).下面是一个简单的例子: RandomAccessFile fromFile = new Rand

Java NIO 通道之间的数据传输(5)

在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个通道传输到另外一个通道. transferFrom() FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中(即为将字节从给定的可读取字节 通道传输到此通道的文件中). 例: RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");File

java nio之 channel通道(二)

java nio 通道上一篇文章里就讲述过,channel总是写数据的时候,要先把数据写入到bytebuffer,读数据的时候总是要先从channel中读入到bytebuffer.如下图,这个图是好多知名博客常用的图,很好理解这个channel. channel分为一下几种: FileChannel SocketChannel ServerSocketChannel DatagramChannel FileChannel: 经常说的FileChannel都是拿下面的例子说事 代码如下: pack

Java NIO缓冲

缓冲区(buffer)是从即将写入通道(channel)或刚刚从通道中读出的一段数据.它是一个持有数据,并扮演NIO通道端点的对象.缓冲区为数据访问和读写过程提供正式机制. 它是NIO和老版Java I/O的一个主要区别.之前数据是直接从流(stream)中读写的,现在数据可以从缓冲区读写.在NIO中,通道是流的同义词.想要了解更多关于NIO通道的信息, 请阅读上一篇教程Java NIO通道. NIO缓冲区特征 Java NIO的基本组成模块就是缓冲区. 缓冲区提供一个固定大小的容器来读取数据.

Java NIO 缓冲技术详解

缓冲区(buffer)是从即将写入通道(channel)或刚刚从通道中读出的一段数据.它是一个持有数据,并扮演NIO通道端点的对象.缓冲区为数据访问和读写过程提供正式机制. 它是NIO和老版Java I/O的一个主要区别.之前数据是直接从流(stream)中读写的,现在数据可以从缓冲区读写.在NIO中,通道是流的同义词.想要了解更多关于NIO通道的信息, 请阅读上一篇教程Java NIO通道. NIO缓冲区特征 Java NIO的基本组成模块就是缓冲区. 缓冲区提供一个固定大小的容器来读取数据.

Java NIO 学习总结 学习手册

原文 并发编程网(翻译):http://ifeve.com/java-nio-all/  源自 http://tutorials.jenkov.com/java-nio/index.html Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. Java NIO: Non-blocking IO(非阻塞IO

Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather

什么是Scatter/Gather scatter/gather指的在多个缓冲区上实现一个简单的I/O操作,比如从通道中读取数据到多个缓冲区,或从多个缓冲区中写入数据到通道: scatter(分散):指的是从通道中读取数据分散到多个缓冲区Buffer的过程,该过程会将每个缓存区填满,直至通道中无数据或缓冲区没有空间: gather(聚集):指的是将多个缓冲区Buffer聚集起来写入到通道的过程,该过程类似于将多个缓冲区的内容连接起来写入通道: scatter/gather接口 如下是Scatte

Java nio 笔记:系统IO、缓冲区、流IO、socket通道

一.Java IO 和 系统 IO 不匹配 在大多数情况下,Java 应用程序并非真的受着 I/O 的束缚.操作系统并非不能快速传送数据,让 Java 有事可做:相反,是 JVM 自身在 I/O 方面效率欠佳.操作系统与 Java 基于流的 I/O模型有些不匹配.操作系统要移动的是大块数据(缓冲区),这往往是在硬件直接存储器存取(DMA)的协助下完成的.而 JVM 的 I/O 操作类喜欢操作小块数据--单个字节.几行文本.结果,操作系统送来整缓冲区的数据,java.io 包的流数据类再花大量时间