四.Channel

一.Channel

  • 通道是用于字節(jié)緩沖區(qū)和位于通道另一邊的數(shù)據(jù)實(shí)體之間執(zhí)行傳輸數(shù)據(jù)。
  • NIO主要分為File IO和Steam IO,對(duì)應(yīng)通道分為Filechannel和SocketChannel(Socketchannel、ServerSocketChannel和DatagramChannel)。File IO沒有非阻塞模式。
  • 通道可以多種方式創(chuàng)建,SocketChannel提供直接創(chuàng)建Socket通道的工廠方法(SocketChannel.open),F(xiàn)ileChannel只能通過一個(gè)打開的RandomAccessFile、FileInputSteam或者FileOutputSteam對(duì)象調(diào)用getChannel方法獲取,不可以直接創(chuàng)建。
  • 本文主要討論Filechannel,非阻塞通信在下節(jié)總結(jié)

二.Filechannel

  • 層次圖
    • 頂層Channel接口提供了isOpen方法判斷通道是否打開和close方法關(guān)閉一個(gè)打開的通道,InterruptibleChannel是一個(gè)標(biāo)志接口,當(dāng)通道使用時(shí)可以標(biāo)志該通道可以被中斷的。WritableByteChannel和ReadableByteChannel表明通道只能字節(jié)緩沖區(qū)上操作。Scatter和Gather表示可以在多個(gè)緩沖區(qū)上執(zhí)行IO操作。
    • FilechannelImlp是其重要子類


      image.png
  • API
    1.map(MapMode mode, long position, long size):可以在一個(gè)打開的文件和一個(gè)特殊類型的ByteBuffer之間建立一個(gè)虛擬內(nèi)存映射(返回一個(gè)MappedByteBuffer對(duì)象)。get方法會(huì)從磁盤文件中獲取文件當(dāng)前的數(shù)據(jù)內(nèi)容,如果建立映射之后文件被其他進(jìn)程修改,對(duì)該進(jìn)程也是可見的。put方法會(huì)更新磁盤上的文件,對(duì)文件的修改對(duì)其他進(jìn)程也是可見的。
    2.read/write(ByteBuffer var1):從Buffe讀數(shù)據(jù),從源碼中可看出讀寫是鎖了整個(gè)線程
public int read(ByteBuffer var1) throws IOException {
            Object var2 = this.positionLock;
            synchronized(this.positionLock) {
                   ........
                   var3 = IOUtil.read(this.fd, var1, -1L, this.nd);   
                   ........
                } finally {
                   .......
                }
            }
        }
    }

三.實(shí)例

  • read(new FileReader("a.txt")):NIO
    readByStream(new File("a.txt")):傳統(tǒng)IO
    readByMap(new File("a.txt")):內(nèi)存映射
package IO;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Created by admin on 2017/9/21.
 */
public class Stream {

    public static void main(String[] args) throws IOException {
        read(new FileReader("a.txt"));
        readByStream(new File("a.txt"));
        readByMap(new File("a.txt"));
        new Thread(new Runnable() {
            @Override
            public void run() {
                readByNio(new File("a.txt"), 2);
            }
        }).start();

    }

    private static void readByStream(File file) {
        BufferedInputStream bs = null;
        BufferedOutputStream fs = null;
        try {
            bs = new BufferedInputStream(new FileInputStream(file));
            fs = new BufferedOutputStream(new FileOutputStream(new File("c.txt")));
            byte[] b = new byte[1024];
            while (bs.read(b) != -1) {
                fs.write(b);
                fs.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //關(guān)閉流,其實(shí)關(guān)閉的就是java調(diào)用的系統(tǒng)底層資源。在關(guān)閉前,會(huì)先刷新該流。
            if (fs != null && fs != null) {
                Integer a = 1;
                try {
                    bs.close();
                    fs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void read(FileReader file) {
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            br = new BufferedReader(file);
            //如果d文件中有數(shù)據(jù),true表示繼續(xù)往文件中追加數(shù)據(jù)
            bw = new BufferedWriter(new FileWriter("d.txt", false));
            String line = null;
            //高效字符輸入流的特有方法readline(),每次讀取一行數(shù)據(jù)
            while ((line = br.readLine()) != null) {
                bw.write(line);
                //高效字符輸出流的特有方法newline()
                bw.newLine();
                //將緩沖區(qū)中的數(shù)據(jù)刷到目的地文件中
                bw.flush();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //關(guān)閉流,其實(shí)關(guān)閉的就是java調(diào)用的系統(tǒng)底層資源。在關(guān)閉前,會(huì)先刷新該流。
            if (bw != null && br != null) {
                try {
                    br.close();
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    private static void readByNio(File file, Integer type) {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        FileChannel channel = null;
        FileChannel channel1 = null;
        String name = "";
        if (type == 1) {
            name = "b.txt";
        } else {
            name = "c.txt";
        }
        try {
            fileInputStream = new FileInputStream(file);
            fileOutputStream = new FileOutputStream(new File(name));
            channel1 = fileOutputStream.getChannel();
            channel = fileInputStream.getChannel();
            ByteBuffer buf = ByteBuffer.allocate(1024);
            int read = channel.read(buf);
            while (read != -1) {
                buf.flip();
                while (buf.hasRemaining()) {
                    channel1.write(buf);
                }
                buf.compact();
                read = channel.read(buf);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (channel1 != null) {
                try {
                    channel1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void readByMap(File file) {
        FileChannel a = null;
        FileChannel b=null;
        try {
            a = new RandomAccessFile("a.txt", "rw").getChannel();
            b = new RandomAccessFile("e.txt", "rw").getChannel();
            MappedByteBuffer in = a.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
            MappedByteBuffer out = b.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
            out.put(in);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (a!=null){
                    a.close();
                }
                if (b!=null){
                    a.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自 http://www.ibm.com/developerworks/cn/education/java/j-...
    抓兔子的貓閱讀 2,485評(píng)論 0 22
  • Java NIO(New IO)是從Java 1.4版本開始引入的一個(gè)新的IO API,可以替代標(biāo)準(zhǔn)的Java I...
    JackChen1024閱讀 7,940評(píng)論 1 143
  • 前言: 之前的文章《Java文件IO常用歸納》主要寫了Java 標(biāo)準(zhǔn)IO要注意的細(xì)節(jié)和技巧,由于網(wǎng)上各種學(xué)習(xí)途徑,...
    androidjp閱讀 3,239評(píng)論 0 22
  • java nio Java的IO體系:舊IO新IO:nio,用ByteBuffer和FileChannel讀寫ni...
    則不達(dá)閱讀 914評(píng)論 0 2
  • 傳統(tǒng)IO和普通IO的區(qū)別 傳統(tǒng)IO:面向流,阻塞IO(Blocking), selector NIO:面向緩沖區(qū),...
    he_321閱讀 693評(píng)論 0 4

友情鏈接更多精彩內(nèi)容