通道(Channel)的原理與獲取


通道(Channel):由 java.nio.channels 包定義 的。Channel 表示 IO 源與目標打開的連接。

                               Channel 類似於傳統的“流”。只不過 Channel 本身不能直接訪問數據,Channel 只能與 Buffer 進行交互

 

TestChannel

package com.aff.nio;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
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;

import org.junit.Test;

/*
 * 1.通道(channel):用於源節點於目標節點的連接,在Java NIO中負責緩沖區數據的傳輸。
 * channel本身不存儲數據的,因此需要配合緩沖區傳輸‘
 * 2.通道的主要實現類
 *  java.nio.channels.Channel接口
 *     |FileChannel    本地的文件通道
 *     |SocketChannel   網絡 TCP
 *     |ServerSocketChannel  網絡TCP
 *     |DatagramChannel    網絡 UDP
 *  
 * 3.獲取通道
 *       ①.java針對支持通道的類提供了getChannel()方法
 *  
 *                 本地:
 *                       FileInputStream/FileOutputStream
 *                       RandomAccessFile//隨機存儲文件流
 *  
 *                 網絡IO:
 *                       Socket
 *                       ServerSocket
 *                       DatagremSocket
 *  
 *       ②.jdk1.7NIO.2針對各個通道提供靜態方法open()
 *       ③.jdk1.7中的NIO.2的Files工具類的newByteChannel()
 *  4.通道之間的數據傳輸
 *    transferFrom()
 *    transferTo()
 *  
 *  5.
 *  分散(Scatter)與聚集(Gather)
 *  分散讀取(Scattering Reads):將通道中的數據分散到多個緩沖區中
 *  聚集寫入(Gathering Writes):將多個緩沖區中的數據聚集到通道中
 *  
 *  6.字符集:Charset  
 *  編碼:字符串->字節數組
 *  解碼:字節數組->字符串
 */
public class TestChannel {

    // 分散和聚集
    @Test
    public void test4() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("11.txt", "rw");
        // 分散讀取,通道中數據分散到多個緩沖區中
        // 1.獲取通道
        FileChannel channel = raf.getChannel();
        // 2.分配通道大小
        ByteBuffer buf1 = ByteBuffer.allocate(100);
        ByteBuffer buf2 = ByteBuffer.allocate(500);
        // 3.分散讀取
        ByteBuffer[] bufs = { buf1, buf2 };
        channel.read(bufs);
        for (ByteBuffer by : bufs) {
            by.flip();
        }
        System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
        System.out.println("=================");
        System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));

        // 4.聚集寫入
        RandomAccessFile raf2 = new RandomAccessFile("16.txt", "rw");
        FileChannel channel2 = raf2.getChannel();
        channel2.write(bufs);
    }

    // 通道之間的數據傳輸(直接緩沖區)
    @Test
    public void test3() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"),
StandardOpenOption.READ); FileChannel outChannel
= FileChannel.open(Paths.get("4.jpg"),
StandardOpenOption.WRITE,
StandardOpenOption.READ,StandardOpenOption.CREATE);
inChannel.transferTo(
0, inChannel.size(), outChannel);
// 從inchannel來到outchannel中去 // inChannel.transferTo(position, count, target) // outChannel.transferFrom(inChannel, 0, inChannel.size()); // outChannel.transferFrom(src, position, count) } // 使用直接緩沖區完成文件的復制(內存映射文件的方) @Test public void test2() throws Exception { long start = System.currentTimeMillis(); FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"),
StandardOpenOption.READ); FileChannel outChannel
= FileChannel.open(Paths.get("3.jpg"),
StandardOpenOption.WRITE,StandardOpenOption.READ,
StandardOpenOption.CREATE);
// 內存映射文件 MappedByteBuffer inMappedByteBuffer = inChannel.map(MapMode.READ_ONLY, 0,
inChannel.size()); MappedByteBuffer outMappedByteBuffer
= outChannel.map(MapMode.READ_WRITE, 0,
inChannel.size());
// 直接對緩沖區進行數據的讀寫操作 byte[] dst = new byte[inMappedByteBuffer.limit()]; inMappedByteBuffer.get(dst); outMappedByteBuffer.put(dst); inChannel.close(); outChannel.close(); long end = System.currentTimeMillis(); System.out.println("時間為:" + (end - start));// 7 } // 使用通道完成文件的復制(非直接緩沖區) @Test public void test1() throws FileNotFoundException { long start = System.currentTimeMillis(); FileInputStream fis = null; FileOutputStream fos = null; FileChannel inchannel = null; FileChannel outchannel = null; try { fis = new FileInputStream("1.jpg"); fos = new FileOutputStream("2.jpg"); // 1.獲取通道 inchannel = fis.getChannel(); outchannel = fos.getChannel(); // 2.分配指定大小的緩沖區 ByteBuffer buf = ByteBuffer.allocate(1024); // 3.將通道中的數據存入緩沖區中 while ((inchannel.read(buf)) != -1) { buf.flip(); // 然后切換成讀取模式,再輸出 // 4.將緩沖區的數據寫入通道中 outchannel.write(buf); buf.clear();// 清空緩沖區 } } catch (IOException e) { e.printStackTrace(); } finally { if (outchannel != null) { try { outchannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (inchannel != null) { try { inchannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } long end = System.currentTimeMillis(); System.out.println("時間為:" + (end - start));// 146 } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM