1. 程式人生 > >java NIO 的通道Channel的理解

java NIO 的通道Channel的理解

一、什麼是通道?

Channel,中文意思“通道”,表示IO源與目標開啟的連線,類似於傳統的“流”。但是Channel不能直接訪問資料,

需要和緩衝區buffer進行互動。打個比喻:山西有煤,我們想要,於是乎建了一條鐵路連通到山西,

這條鐵路就是這裡的"Channel",那麼煤通過什麼運過來呢?鐵路建好了,就差火車了,

因此這裡的火車就像是緩衝區,火車把山西的煤運到這邊來,把我們這裡的錢運過去,

這樣雙向傳輸就愉快的完成了。Channel類似於傳統的“流”,只不過Channel不能直接訪問資料,

Channel只能與buffer互動。而且流是單向的,分為輸入流和輸出流, 但是通道是雙向的,

通過緩衝區buffer兩邊都可達。Channel表示IO源與目標開啟的連線。工作原理如下,通過Channel來獨立處理IO請求:

                                          

二、主要實現類:

   FileChannel:用於讀取、寫入、對映和操作檔案的通道。

DatagramChannel:通過UDP讀寫網路中的資料通道。

SocketChannel:通過tcp讀寫網路中的資料。

ServerSocketChannel:可以監聽新進來的tcp連線,對每一個連線都建立一個SocketChannel。

三、獲取通道的方式

1、通過getChannel()方法獲取

前提是該類支援該方法。支援該類的方法有:

FileInputStream/FileOutputStream,RandomAccessFile,Socket,ServerSocket ,DatagramSocket

2、通過靜態方法open()

3、通過jdk1.7中Files的newByteChannel()方法

四、通道資料傳輸

通過一段複製圖片的程式碼解釋:

1、利用通道和非直接緩衝區完成

FileInputStream fis=null;           //引用
		FileOutputStream fout=null;
		FileChannel channel=null;//通道引用
		FileChannel outchannel=null;
		try {
			fis = new FileInputStream("sb.jpg");     //原始檔
			fout = new FileOutputStream("bb.jpg");	 //目標檔案	  	
			channel = fis.getChannel();             //獲取連線原始檔的通道
			outchannel = fout.getChannel();	        //獲取連線目標檔案的通道
			//指定緩衝區 非直接緩衝區
			ByteBuffer buffer=ByteBuffer.allocate(1024);  //建立緩衝區 用來傳輸資料
			while(channel.read(buffer)!=-1)          //從連線原始檔的管道讀取資料到緩衝區
			{
				//將緩衝區反轉
				buffer.flip();
				outchannel.write(buffer);        //將緩衝區中的資料寫入連線到目標檔案的管道
				buffer.clear();                  //"清空"緩衝區
			}
2、利用通道和記憶體對映檔案完成
		FileChannel inChannel=FileChannel.open(Paths.get("C:\\Users\\Administrator\\Pictures\\picture\\1.jpg"), StandardOpenOption.READ);
//引數1表示目標檔案或者原始檔的路徑,引數2是可以是多個引數,表示通道支援的操作型別
FileChannel outChannel=FileChannel.open(Paths.get("C:\\Users\\Administrator\\Pictures\\picture\\1bar.jpg"),
StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
		//記憶體對映檔案 相當於之前的緩衝區
		MappedByteBuffer inBuffer=inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());		
		MappedByteBuffer outBuffer=outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
		//直接對緩衝區讀寫操作
		byte[] data=new byte[inBuffer.limit()];
		//將資料讀入位元組陣列
		inBuffer.get(data);
		outBuffer.put(data);   //寫入管道
		inChannel.close();
		outChannel.close();
對於上面這種方式,可以很大程度上提高程式的效率。那麼怎麼提高的呢?

回到最上面的那張通道工作的原理圖,使用者地址和記憶體地址都有一個緩衝區,它們之間有一個copy過程,也就是說程式的資料要先到jvm使用者地址緩衝區,再到計算機記憶體中。也就是不能直接和計算機記憶體進行資料操作。那麼通過記憶體對映檔案呢,也就是上訴方式,內部以直接緩衝區和記憶體對映檔案實現了直接訪問記憶體。這樣大大提高了效率。但是也有缺點,如果寫過去的資料很大,然後jvm沒有及時回收記憶體,那麼結果可想而知。因此,這個適用於那種長久存放在記憶體不應該被短時間內就需要回收的資料。

3、通道之間的直接傳輸

FileChannel inChannel=FileChannel.open(Paths.get("C:\\Users\\Administrator\\Pictures\\picture\\1.jpg"), StandardOpenOption.READ);
		FileChannel outChannel=FileChannel.open(Paths.get("C:\\Users\\Administrator\\Pictures\\picture\\1bar.jpg"), 
StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
		//transfer方法   內部是直接緩衝區的方式實現
		//inChannel.transferTo(0,inChannel.size(), outChannel);
		outChannel.transferFrom(inChannel, 0, inChannel.size());
		inChannel.close();
		outChannel.close();
咦?為什麼上面的程式碼沒有緩衝區呢?不是說通道不能直接訪問資料嗎?

沒錯,只不過在transferTo和transferFrom內部實現了緩衝區,所以資料還是通過緩衝區來完成的。

關於transferTo和transferFrom,兩者達到的效果一樣,只是使用的方式不同,前者是原始檔到目標檔案,

後者是目標檔案的資源來自於原始檔。

4、分散於聚集

分散讀取:是指讀取一個Channel的資料到多個buffer中,注意是依次填滿每個緩衝區,直到沒有資料了;

聚集寫入:是指將多個buffer的內容依次寫入到通道中。

RandomAccessFile randomAccessFile=new RandomAccessFile("1.txt", "rw");
		FileChannel channel=randomAccessFile.getChannel();//獲取通道
		//分配指定大小緩衝區  這裡指定兩個大小不一樣的緩衝區
		ByteBuffer buf1=ByteBuffer.allocate(100);
		ByteBuffer buf2=ByteBuffer.allocate(4096);
		ByteBuffer[] buf={buf1,buf2};
		channel.read(buf);
		for (ByteBuffer byteBuffer : buf) {
			byteBuffer.flip();     //翻轉 開啟讀模式
		}
		//列印buf1的內容
		System.out.println(new String(buf[0].array(),0,buf[0].limit()));
		//列印buf2的內容
		System.out.println(new String(buf[1].array(),0,buf[1].limit()));
		//聚集寫入
		RandomAccessFile randFile=new RandomAccessFile("2.txt", "rw");
		FileChannel fileChannel=randFile.getChannel();
		fileChannel.write(buf);

相關推薦

Java NIO通道(Channel)

NIO 中主要的三個概念為緩衝區、通道、選擇器,它們之間的關係如下所示: 此處要提醒的是,JDK 1.7 升級了 NIO 類庫,升級後的 NIO 類庫被稱為 NIO2.0。在 NIO2.0 中,提供了非同步檔案I/O操作,同時提供了與 UNIX 網路程式設計事

java niochannel通道(二)

java niojava nio 通道上一篇文章裏就講述過,channel總是寫數據的時候,要先把數據寫入到bytebuffer,讀數據的時候總是要先從channel中讀入到bytebuffer。如下圖,這個圖是好多知名博客常用的圖,很好理解這個channel。channel分為一下幾種:FileChanne

Java NIO 通道Channel) 學習筆記

 一、通道(Channel):用於源節點與目標節點的連線。在 Java NIO 中負責緩衝區中資料的傳輸。Channel 本身不儲存資料,因此需要配合緩衝區進行傳輸。    二、通道的主要實現類      java.nio.c

java niochannel

host 不能 config wrap span bsp cal targe ext   一、通道(Channel):由 java.nio.channels 包定義的。Channel 表示 IO 源與目標打開的連接。Channel 類似於傳統的“流”。只不過 Channel

Java NIO 通道

一、通道(Channel):用於源節點與目標節點的連線。在 Java NIO 中負責緩衝區中資料的傳輸。Channel 本身不儲存資料,因此需要配合緩衝區進行傳輸。     二、通道的主要實現類    java.nio.channels.Cha

Java NIO 通道的實現型別

檔案通道Java NIO中的FileChannel是一個連線到檔案的通道。可以通過檔案通道讀寫檔案。 FileChannel無法設定為非阻塞模式,它總是執行在阻塞模式下。 開啟FileChannel 在使用FileChannel之前,必須先開啟它。但是,我們無法直接開啟一個F

Java NIO Buffer Channel Selector

1、緩衝區型別: ByteBuffer CharBuffer ShortBufer IntBuffer LongBuffer FloatBuffer DoubleBuffer,並沒有 BooleanBuffer 2、ByteBuffer 基本操作 import java

Java NIO 通道(二)通道基礎

概念通道是NIO提供的一個全新的東西,提供與I/O服務的直接連線。Channel用於在位元組緩衝區和位於通道的另一側的實體(通常是一個檔案或者套接字)之間進行有效的傳輸資料。介面定義 public interface Channel extends Closea

Java nioChannel介面繼承了Closeable,為什麼還要有close() 方法

首先Api是這樣給出的: Closeable的close()方法: void close() throws IOException Closes this stream and

java NIO通道Channel理解

一、什麼是通道? Channel,中文意思“通道”,表示IO源與目標開啟的連線,類似於傳統的“流”。但是Channel不能直接訪問資料, 需要和緩衝區buffer進行互動。打個比喻:山西有煤,我們想要

Java NIO深入理解Channel(通道)

一 Channel概述通道Channel由java.nio.channels包定義。Channel表示IO源與目標開啟的連線。Java NIO的通道類似流,Channel本身不能直接訪問資料,Channel只能與Buffer進行互動。既可以從通道中讀取資料,又可以寫資料到通道

Java NIO通道Channel分析

目錄 簡介 檔案通道FileChannel Socket通道 其他內容                              &n

java nio系列教程(2)---channel(通道介紹)和使用

大家推薦個靠譜的公眾號程式設計師探索之路,大家一起加油 ​   package com.zzh.buffer; import com.google.common.collect.Lists; import org.junit.jupiter.api.Test; imp

Java NIO(二)通道Channel

一、通道(Channel): 用於源節點與目標節點的連線。在 Java NIO 中負責緩衝區中資料的傳輸。Channel 本身不儲存資料,因此需要配合緩衝區進行傳輸。  二、通道的主要實現類      java.nio.channels.C

Java NIO怎麼理解通道和非阻塞?

nio引入了buffer、channel、selector等概念。 通道相當於之前的I/O流。 “通道”太抽象了。java解釋不清的東西只能看它底層是怎麼解釋的——作業系統的I/O控制,通道控制方式? I/O裝置:CPU——通道——裝置控制器——I/O裝置 (通道和裝置控制

Java NIO深入理解通道之間資料傳輸

在Java NIO中,如果兩個通道中有一個是FileChannel,那你可以直接將資料從一個channel(通道)傳輸到另外一個channel。通道之間資料傳輸方法:transferFrom(),transferTo() transferFrom()FileChannel的

JAVA NIO(三)通道Channel & 直接與非直接緩衝區

1. 通道負責目標節點與源節點的連線;傳輸資料。在 Java NIO 中負責緩衝區中資料的傳輸。Channel 本身不儲存資料,因此需要配合緩衝區進行傳輸。2.通道的主要實現類  java.nio.channels.Channel 介面:  |--FileChannel  |

JavaNIOChannel通道

1.Channel 通道的簡介 java的NIO的通道類似流,但是又有一些不同: - 既可以從Channel中讀資料也可以往Channel裡面寫資料;但是流的讀寫一般是單向的。 - Channel

Java NIO通道Channel)的使用

通道(Channel)的使用說明 /** * <pre> * 一、通道(Channel):用於源節點與目標節點的連線。在 Java NIO 中負責緩衝區中資料的傳輸。 * Channel 本身不儲存資

Java NIO 之 Socket Channel

狀態 servers ext exc sync ini 並且 interface bsp   在Java NIO中用Channel來對程序與進行I/O操作主體的連接關系進行抽象,這些IO主體包括如文件、Socket或其他設備。簡而言之,指代了一種與IO操作對象間的連接關系。