国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 Java Java入門 詳細(xì)介紹Java NIO

詳細(xì)介紹Java NIO

Oct 21, 2020 pm 04:35 PM
java nio

詳細(xì)介紹Java NIO

Java NIO主要需要理解緩衝區(qū)、通道、選擇器三個(gè)核心概念,作為Java I/O的補(bǔ)充, 以提升大量資料傳輸?shù)男省?

(推薦教學(xué):java課程

學(xué)習(xí)NIO之前最好能有基礎(chǔ)的網(wǎng)路程式設(shè)計(jì)知識

Java I/O串流

Java 網(wǎng)路程式設(shè)計(jì)

Java NIO:緩衝區(qū)

通道(Channel)作為NIO的三大核心概念之一(緩衝區(qū)、通道、選擇器),用於在位元組緩衝區(qū)與位於通道另一側(cè)的實(shí)體(檔案或套接字)之間有效的傳輸資料(核心是傳輸資料)

NIO程式設(shè)計(jì)的一般模式是:將資料填入傳送字節(jié)緩衝區(qū)--> 透過通道傳送到通道對端檔案或套接字

通道基礎(chǔ)

使用Channel的目的是進(jìn)行資料傳輸,使用前需要打開通道、使用後需要關(guān)閉通道

打開通道

我們知道I/O有兩大類:File IO和Stream I/O,其對應(yīng)到通道也就有檔案通道(FileChannel)和套接字通道(SocketChannel、ServerSocketChannel、DatagramChannel)兩種

對於套接字通道,使用靜態(tài)工廠方法開啟

SocketChannel sc = SocketChannel.open();
ServerSocketChannel sc = ServerSocketChannel.open();
DatagramChannel sc = DatagramChannel.open();

對於檔案通道只能透過對一個(gè)RandomAccessFile、FileInputStream、FileOutputStream物件呼叫g(shù)etChannel()方法取得

FileInputStream in = new FileInputStream("/tmp/a.txt");
FileChannel fc = in.getChannel();

使用通道進(jìn)行資料傳輸

下段程式碼首先將要寫入的資料放到ByteBuffer中, 然後開啟檔案通道,把緩衝區(qū)中的資料放到檔案通道。

//準(zhǔn)備數(shù)據(jù)并放入字節(jié)緩沖區(qū)
ByteBuffer bf = ByteBuffer.allocate(1024);
bf.put("i am cool".getBytes());
bf.flip();
//打開文件通道
FileOutputStream out = new FileOutputStream("/tmp/a.txt");
FileChannel fc = out.getChannel();
//數(shù)據(jù)傳輸
fc.write(bf);
//關(guān)閉通道
fc.close();

關(guān)閉通道

如同Socket、FileInputStream等物件使用完畢之後需要關(guān)閉一樣, 通道使用之後也需要關(guān)閉。一個(gè)打開的通道代表與一個(gè)特定I/O服務(wù)的特定連接並封裝該連接的狀態(tài),通道關(guān)閉時(shí)連接丟失,不再連接任何東西。

阻塞& 非阻塞模式

通道有阻塞和非阻塞兩種運(yùn)作模式,非阻塞模式的通道永遠(yuǎn)不會(huì)休眠,請求的操作要麼立即完成,要么返回一個(gè)結(jié)果表明未進(jìn)行任何操作(具體看Socket通道處的描述)。只有面向流的通道可使用非阻塞模式

文件通道

文件通道用於對文件進(jìn)行訪問, 透過對一個(gè)RandomAccessFile、FileInputStream、FileOutputStream物件呼叫g(shù)etChannel ()方法取得。呼叫g(shù)etChannel方法傳回一個(gè)連接到相同檔案的FileChannel對象,該FileChannel物件具有與file對象相同的存取權(quán)。

檔案存取

使用檔案通道的目的還是對檔案進(jìn)行讀寫操作,通道的讀寫api如下:

public abstract int read(ByteBuffer dst) throws IOException;
public abstract int write(ByteBuffer src) throws IOException;

下面是一段讀取檔案的Demo

//打開文件channel
RandomAccessFile f = new RandomAccessFile("/tmp/a.txt", "r");
FileChannel fc = f.getChannel();
//從channel中讀取數(shù)據(jù),直到文件尾
ByteBuffer bb = ByteBuffer.allocate(1024);
while (fc.read(bb) != -1) {
;
}
//翻轉(zhuǎn)(讀之前需要先進(jìn)行翻轉(zhuǎn))
bb.flip();
StringBuilder builder = new StringBuilder();
//把每一個(gè)字節(jié)轉(zhuǎn)為字符(ascii編碼)
while (bb.hasRemaining()) {
builder.append((char) bb.get());
}
System.out.println(builder.toString());

上面這個(gè)demo有個(gè)問題:我們只能讀取字節(jié), 然後由應(yīng)用程式去解碼,這個(gè)問題我們可以透過工具類Channels將通道包裝成Reader和Writer來解決;當(dāng)然我們也可以直接使用Java I/O流模式的Reader和Writer操作字符

#文件通道位置與文件空洞

文件通道位置(position)就是普通檔案的位置, position的值決定了檔案中哪個(gè)位置的資料接下來將被讀取或?qū)懭?/p>

#讀取超出檔案尾部位置的資料會(huì)回傳-1(檔案EOF)

往一個(gè)超出檔案尾部的位置寫入資料會(huì)造成檔案空洞:例如一個(gè)檔案現(xiàn)在有10個(gè)位元組, 但是此時(shí)往position=20 處寫入資料就會(huì)造成10~20之間的位置是沒有資料的,這就是檔案空洞

force操作

force操作強(qiáng)制通道將全部修改立即套用到磁碟檔案(防止系統(tǒng)宕機(jī)導(dǎo)致修改遺失)

public abstract void force(boolean metaData) throws IOException;

記憶體檔案對應(yīng)

FileChannel提供了一個(gè)map()方法,可以在一個(gè)開啟的檔案和特殊類型的ByteBuffer(MappedByteBuffer)之間建立一個(gè)虛擬記憶體映射。

因?yàn)閙ap方法傳回的MappedByteBuffer物件是直接緩衝區(qū),所以透過MappedByteBuffer來操作檔案非常有效率(尤其是大量資料傳輸?shù)那闆r)

MappedByteBuffer的使用

透過MappedByteBuffer讀取檔案

FileInputStream in = new FileInputStream("/tmp/a.txt");
FileChannel fc = in.getChannel();
MappedByteBuffer mbb = fc.map(MapMode.READ_ONLY, 0, fc.size());
StringBuilder builder = new StringBuilder();
while (mbb.hasRemaining()) {
  builder.append((char) mbb.get());
}
System.out.println(builder.toString());

MappedByteBuffer的三種模式

READ_ONLY

#READ_WRITE

PRIVATE

只讀和讀寫模式都好理解,PRIVATE模式下寫操作寫的是一個(gè)暫存緩衝區(qū),不會(huì)真正去寫檔案。 (寫時(shí)拷貝思想)

Socket通道

Socket 通道可以運(yùn)行在非阻塞模式且是可選擇的,這兩點(diǎn)使得對於網(wǎng)路程式設(shè)計(jì)我們不再需要為每個(gè)Socket連線建立一個(gè)線程,而是使用一個(gè)線程即可管理成百上千的Socket連線。

所有的Socket通道在實(shí)例化的時(shí)候都會(huì)創(chuàng)建一個(gè)對象的Socket對象, Socket通道並不負(fù)責(zé)協(xié)議相關(guān)的操作, 協(xié)議相關(guān)的操作都委派給對等socket對象(如SocketChannel對象委派給Socket物件)

非阻塞模式

相較于傳統(tǒng)Java Socket的阻塞模式,SocketChannel提供了非阻塞模式,以構(gòu)建高性能的網(wǎng)絡(luò)應(yīng)用程序

非阻塞模式下,幾乎所有的操作都是立刻返回的。比如下面的SocketChannel運(yùn)行在非阻塞模式下,connect操作會(huì)立即返回,如果success為true代表連接已經(jīng)建立成功了, 如果success為false, 代表連接還在建立中(tcp連接需要一些時(shí)間)。

 //打開Socket通道
 SocketChannel ch = SocketChannel.open();
 //非阻塞模式
 ch.configureBlocking(false);
 //連接服務(wù)器 
 boolean success = ch.connect(InetSocketAddress.createUnresolved("127.0.0.1", 7001));
 //輪訓(xùn)連接狀態(tài), 如果連接還未建立就可以做一些別的工作
 while (!ch.finishConnect()){
    //dosomething else
 }
 //連接建立, 做正事
 //do something;

ServerSocketChannel

ServerSocketChannel與ServerSocket類似,只是可以運(yùn)行在非阻塞模式下

下為一個(gè)通過ServerSocketChannel構(gòu)建服務(wù)器的簡單例子,主要體現(xiàn)了非阻塞模式,核心思想與ServerSocket類似

ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.bind(new InetSocketAddress(7001));
while (true){
  SocketChannel sc = ssc.accept();
  if(sc != null){
    handle(sc);
  }else {
    Thread.sleep(1000);
  }
}

SocketChannel 與 DatagramChannel

SocketChannel 對應(yīng) Socket, 模擬TCP協(xié)議;DatagramChannel對應(yīng)DatagramSocket, 模擬UDP協(xié)議

二者的使用與SeverSocketChannel大同小異,看API即可

工具類

文體通道那里我們提到過, 通過只能操作字節(jié)緩沖區(qū), 編解碼需要應(yīng)用程序自己實(shí)現(xiàn)。如果我們想在通道上直接操作字符,我們就需要使用工具類Channels,工具類Channels提供了通道與流互相轉(zhuǎn)換、通道轉(zhuǎn)換為閱讀器書寫器的能力,具體API入下

//通道 --> 輸入輸出流
public static OutputStream newOutputStream(final WritableByteChannel ch);
public static InputStream newInputStream(final AsynchronousByteChannel ch);
//輸入輸出流 --> 通道
public static ReadableByteChannel newChannel(final InputStream in);
public static WritableByteChannel newChannel(final OutputStream out);
//通道  --> 閱讀器書寫器
public static Reader newReader(ReadableByteChannel ch, String csName);
public static Writer newWriter(WritableByteChannel ch, String csName);

通過將通道轉(zhuǎn)換為閱讀器、書寫器我們就可以直接在通道上操作字符。

    RandomAccessFile f = new RandomAccessFile("/tmp/a.txt", "r");
  FileChannel fc = f.getChannel();
  //通道轉(zhuǎn)換為閱讀器,UTF-8編碼
  Reader reader = Channels.newReader(fc, "UTF-8");
  int i = 0, s = 0;
  char[] buff = new char[1024];
  while ((i = reader.read(buff, s, 1024 - s)) != -1) {
    s += i;
  }
  for (i = 0; i < s; i++) {
    System.out.print(buff[i]);
  }

總結(jié)

通道主要分為文件通道和套接字通道。

對于文件操作:如果是大文件使用通道的文件內(nèi)存映射特性(MappedByteBuffer)來有利于提升傳輸性能, 否則我更傾向傳統(tǒng)的I/O流模式(字符API);對于套接字操作, 使用通道可以運(yùn)行在非阻塞模式并且是可選擇的,利于構(gòu)建高性能網(wǎng)絡(luò)應(yīng)用程序。

相關(guān)推薦:java入門

以上是詳細(xì)介紹Java NIO的詳細(xì)內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)