程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 【JAVA NIO】Channels和Buffers,niobuffers

【JAVA NIO】Channels和Buffers,niobuffers

編輯:JAVA綜合教程

【JAVA NIO】Channels和Buffers,niobuffers


Channels和Buffers是JAVA NIO裡面比較重要的兩個概念,NIO正是基於Channels和Buffers進行數據操作,且數據總是從Channels讀取到Buffers,或者從Buffers寫入到Channels。

通道(Channel)

  • 可以從通道寫輸入,也可以讀數據;
  • 通道的數據是跟Buffer進行交互的,數據可以讀到Buffer,也可以從Buffer寫數據到通道;
  • 還可以異步讀寫數據;

以FileChannel為例,如下:

FileChannel

FileChannel是文件寫入/讀取相關的通道;

產生FileChannel的方式:

  • 從FileOutputStream中獲取;
  • 從RandomAccessFile中獲取;
  • 從FileInputStream中獲取;

下面舉個例子,分別從FileOutputStream、RandomAccessFile、FileInputStream中獲取文件通道,進行相關寫入/讀取操作;

package com.pichen.io;

import java.nio.*;
import java.nio.channels.*;
import java.io.*;

public class GetChannel {
    private static final int BSIZE = 1024;

    public static void main(String[] args) throws Exception {
        // 創建文件輸出字節流
        FileOutputStream fos = new FileOutputStream("data.txt");
        //得到文件通道
        FileChannel fc = fos.getChannel();
        //往通道寫入ByteBuffer
        fc.write(ByteBuffer.wrap("Some text ".getBytes()));
        //關閉流
        fos.close();

        //隨機訪問文件
        RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");
        //得到文件通道
        fc = raf.getChannel();
        //設置通道的文件位置 為末尾
        fc.position(fc.size()); 
        //往通道寫入ByteBuffer
        fc.write(ByteBuffer.wrap("Some more".getBytes()));
        //關閉
        raf.close();
        
        //創建文件輸入流
        FileInputStream fs = new FileInputStream("data.txt");
        //得到文件通道
        fc = fs.getChannel();
        //分配ByteBuffer空間大小
        ByteBuffer buff = ByteBuffer.allocate(BSIZE);
        //從通道中讀取ByteBuffer
        fc.read(buff);
        //調用此方法為一系列通道寫入或相對獲取 操作做好准備
        buff.flip();
        //從ByteBuffer從依次讀取字節並打印
        while (buff.hasRemaining()){
            System.out.print((char) buff.get());
        }
        fs.close();
    }
} 

再舉個文件復制的例子,有兩種方式:

  • 打開一個FileChannel用於讀,另一個用於寫;
  • 直接調用transferTo或者transferFrom方法傳輸通道之間的數據;

如下代碼示例:

package com.pichen.io;

import java.nio.*;
import java.nio.channels.*;
import java.io.*;

public class ChannelCopy {
    private static final int BSIZE = 1024;

    public static void main(String[] args) throws Exception {
        //獲取文件輸入輸出字節流
        FileInputStream fis = new FileInputStream("C:\\test.jpg");
        FileOutputStream fos = new FileOutputStream("C:\\test_copy.jpg");
        
        //從文件輸入輸出字節流中獲取通道
        FileChannel fci = fis.getChannel();
        FileChannel fco = fos.getChannel();
        //分配ByteBuffer空間大小
        ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
        
        //第一種種數據拷貝方式,直接往輸入通道寫數據
        while (fci.read(buffer) != -1) {
            //為寫入操作做准備
            buffer.flip(); 
            //往輸出通道寫入buffer
            fco.write(buffer);
            //清空buffer,重置內部指針
            buffer.clear(); 
        }
        
        //第二種數據拷貝方式,利用transferTo或者transferFrom方式
        FileOutputStream fos2 = new FileOutputStream("C:\\test_copy2.jpg");
        FileChannel fco2 = fos.getChannel();
        fci.transferTo(0, fci.size(), fco2);
        
        
        fis.close();
        fos.close();
        fos2.close();
    }
}

緩沖區(Buffer)

buffer用於與通道進行交互,舉個例子如下,這裡以ByteBuffer為例;

package com.pichen.io;

import java.nio.*;
import java.nio.channels.*;
import java.io.*;

public class GetChannel {
    private static final int BSIZE = 1024;

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

        // 隨機訪問文件
        RandomAccessFile raf = new RandomAccessFile("C:\\data.txt", "rw");
        // 得到文件通道
        FileChannel fc = raf.getChannel();

        ByteBuffer bf = ByteBuffer.allocate(BSIZE);

        int bytesRead = fc.read(bf); // read into buffer.
        while (bytesRead != -1) {
            // 通過flip()方法將Buffer從寫模式切換到讀模式
            bf.flip();
            while (bf.hasRemaining()) {
                // 每次讀取一個字節
                System.out.print((char) bf.get());

            }

            // 清空緩存,准備往緩存寫數據
            bf.clear();
            bytesRead = fc.read(bf);
        }

        // 關閉
        raf.close();
    }
}

Buffer基本方法

  • flip方法:從buffer讀數據之前調用,從寫模式切換到讀模式;
  • clear:往buffer寫數據之前調用,全部清除;
  • compact:往buffer寫數據之前調用,只清除已讀取的數據,新寫入的數據會添加到未讀數據末尾;

Buffer基本屬性

  • capacity:buffer空間大小;
  • position:讀寫數據時的指針,指向當前位置;
  • limit:讀數據時,表示當前可讀數據的大小;寫數據時,即buffer大小=capacity;

Buffer的類型

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

Buffer中寫數據

  • 從Channel寫到Buffer,調用通道的read(Buffer buffer)方法
  • put()方法寫到Buffer裡,調用Buffer的put方法

Buffer中讀取數據

  • 從Buffer讀取數據到Channel,調用通道的write(Buffer buffer)方法
  • 使用get()方法從Buffer中讀取數據,調用Buffer的get方法

 

參考:http://ifeve.com/java-nio-all/

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved