1. 程式人生 > >JAVA高階基礎(48)---使用通道完成檔案資料傳輸

JAVA高階基礎(48)---使用通道完成檔案資料傳輸

通道(Channel):傳輸資料

由 java.nio.channels 包定義的。Channel表示IO源與目標開啟的連結。Channel類似於傳統的“流”。只不過Channel本身不能直接訪問資料,Channel只能與 Buffer 進行互動

 IO 改進示意圖

 DMA(直接儲存器訪問)

Java 為 Channel 介面提供的最主要實現類如下:

  • FileChannel:用於讀取、寫入、對映和操作檔案的通道。
  • DatagramChannel:通過 UDP 讀寫網路中的資料通道。
  • SocketChannel:通過 TCP 讀寫網路中的資料。
  • ServerSocketChannel:可以監聽新進來的 TCP 連線,對每一個新進來的連線都會建立一個 SocketChannel。        

獲取通道

本地IO:
        FileInputStream/FileOutPutStream
        RandomAccessFile
網路IO:
        socket
        ServerSocket
        DatagramSocket

獲取通道的其他方式是:

  1. jdk1.7  使用 Files 類的靜態方法 newByteChannel() 獲取位元組通道。
  2. jdk1.7  通過通道的靜態方法 open() 開啟並返回指定通道       

使用通道進行資料傳輸

FileInputStream  /  FileOutputStream 的getChannel()
FileChannle的open(Path path,OpenOpertion ... oo)方法來開啟通道

package org.lanqiao.channel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/*
 * 通過本地IO獲取通道  進行資料傳輸
 */
public class ChannelDemo {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream(new File("Notes.txt"));
		FileOutputStream fos = new FileOutputStream(new File("copy.txt"));
		
		//開闢通道
		FileChannel inChannel = fis.getChannel();
		FileChannel outChannel = fos.getChannel();
		//分配緩衝區
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		//迴圈將輸入讀入到緩衝區
		while((inChannel.read(buffer)) != -1) {
			//將緩衝區有讀模式切換到寫模式
			buffer.flip();
			//將緩衝區中的資料通過輸出通道寫出到膜裱
			outChannel.write(buffer);
			//清空緩衝區
			buffer.clear();
			
		}
		//關閉通道
		inChannel.close();
		outChannel.close();
		
		
		
	}
}
package org.lanqiao.channel;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class ChannelDemo2 {
	public static void main(String[] args) throws IOException {
		//開啟檔案輸入通道
		FileChannel inChannel  = FileChannel.open(Paths.get("Notes.txt"), StandardOpenOption.READ);
		//開啟檔案輸出通道
		FileChannel  outChannel = FileChannel.open(Paths.get("copy2.txt"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
		ByteBuffer buf = ByteBuffer.allocate(1024);
		while((inChannel.read(buf)) != -1) {
			buf.flip();
			outChannel.write(buf);
			buf.clear();
			
		}
		inChannel.close();
		outChannel.close();
	}
}
package org.lanqiao.channel;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/*
 * 使用直接緩衝區(記憶體對映檔案)完成檔案複製
 */
public class ChannelDemo3 {
	public static void main(String[] args) throws IOException {
		FileChannel inChannel = FileChannel.open(Paths.get("Notes.txt"), StandardOpenOption.READ);
		FileChannel outChannel = FileChannel.open(Paths.get("copy3.txt"), StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);
		
		//ByteBuffer buf = ByteBuffer.allocateDirect(1024);
		
		//建立記憶體對映檔案
		MappedByteBuffer inMap = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
		MappedByteBuffer outMap = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
		byte[] buf = new byte[inMap.limit()];
		inMap.get(buf);
		outMap.put(buf);
		
		inChannel.close();
		outChannel.close();
		
		
		
	}
}
package org.lanqiao.channel;

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/*
 * 通道之間直接進行檔案傳輸(直接緩衝區)
 */
public class ChannelDemo4 {
	public static void main(String[] args) throws IOException {
		FileChannel inChannle = FileChannel.open(Paths.get("Notes.txt"), StandardOpenOption.READ);
		FileChannel outChannel = FileChannel.open(Paths.get("copy5.txt"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
		//inChannle.transferTo(0, inChannle.size(), outChannel);
		outChannel.transferFrom(inChannle, 0, inChannle.size());
		inChannle.close();
		outChannel.close();
	}
}