亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

首頁 Java Java入門 詳細介紹Java NIO

詳細介紹Java NIO

Oct 21, 2020 pm 04:35 PM
java nio

詳細介紹Java NIO

Java NIO主要需要理解緩沖區(qū)、通道、選擇器三個核心概念,作為對Java I/O的補充, 以提升大批量數(shù)據(jù)傳輸?shù)男省?/p>

(推薦教程:java課程

學(xué)習(xí)NIO之前最好能有基礎(chǔ)的網(wǎng)絡(luò)編程知識

Java I/O流

Java 網(wǎng)絡(luò)編程

Java NIO:緩沖區(qū)

通道(Channel)作為NIO的三大核心概念之一(緩沖區(qū)、通道、選擇器),用于在字節(jié)緩沖區(qū)與位于通道另一側(cè)的實體(文件或者套接字)之間有效的傳輸數(shù)據(jù)(核心是傳輸數(shù)據(jù))

NIO編程的一般模式是:把數(shù)據(jù)填充到發(fā)送字節(jié)緩沖區(qū) --> 通過通道發(fā)送到通道對端文件或者套接字

通道基礎(chǔ)

使用Channel的目的是進行數(shù)據(jù)傳輸,使用前需要打開通道、使用后需要關(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();

對于文件通道只能通過對一個RandomAccessFile、FileInputStream、FileOutputStream對象調(diào)用getChannel()方法獲取

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

使用通道進行數(shù)據(jù)傳輸

下段代碼首先將要寫入的數(shù)據(jù)放到ByteBuffer中, 然后打開文件通道,把緩沖區(qū)中的數(shù)據(jù)放到文件通道。

//準(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)閉。一個打開的通道代表與一個特定I/O服務(wù)的特定連接并封裝該連接的狀態(tài),通道關(guān)閉時連接丟失,不再連接任何東西。

阻塞 & 非阻塞模式

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

文件通道

文件通道用于對文件進行訪問, 通過對一個RandomAccessFile、FileInputStream、FileOutputStream對象調(diào)用getChannel()方法獲取。調(diào)用getChannel方法返回一個連接到相同文件的FileChannel對象,該FileChannel對象具有與file對象相同的訪問權(quá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)(讀之前需要先進行翻轉(zhuǎn))
bb.flip();
StringBuilder builder = new StringBuilder();
//把每一個字節(jié)轉(zhuǎn)為字符(ascii編碼)
while (bb.hasRemaining()) {
builder.append((char) bb.get());
}
System.out.println(builder.toString());

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

文件通道位置與文件空洞

文件通道位置(position)就是普通文件的位置, position的值決定了文件中哪個位置的數(shù)據(jù)接下來將被讀或者寫

讀取超出文件尾部位置的數(shù)據(jù)會返回-1(文件EOF)

往一個超出文件尾部的位置寫入數(shù)據(jù)會造成文件空洞:比如一個文件現(xiàn)在有10個字節(jié), 但是此時往position=20 處寫入數(shù)據(jù)就會造成10~20之間的位置是沒有數(shù)據(jù)的,這就是文件空洞

force操作

force操作強制通道將全部修改立即應(yīng)用到磁盤文件(防止系統(tǒng)宕機導(dǎo)致修改丟失)

public abstract void force(boolean metaData) throws IOException;

內(nèi)存文件映射

FileChannel提供了一個map()方法,該方法可以在一個打開的文件和特殊類型的ByteBuffer(MappedByteBuffer)之間建立一個虛擬內(nèi)存映射。

因為map方法返回的MappedByteBuffer對象是直接緩沖區(qū),所以通過MappedByteBuffer來操作文件非常高效(尤其是大量數(shù)據(jù)傳輸?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模式下寫操作寫的是一個臨時緩沖區(qū),不會真正去寫文件。(寫時拷貝思想)

Socket通道

Socket 通道可以運行在非阻塞模式且是可選擇的,這兩點使得對于網(wǎng)絡(luò)編程我們不再需要為每個Socket連接創(chuàng)建一個線程,而是使用一個線程即可管理成百上千的Socket連接。

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

非阻塞模式

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

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

 //打開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類似,只是可以運行在非阻塞模式下

下為一個通過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)用程序自己實現(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);對于套接字操作, 使用通道可以運行在非阻塞模式并且是可選擇的,利于構(gòu)建高性能網(wǎng)絡(luò)應(yīng)用程序。

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

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

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

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機

Video Face Swap

Video Face Swap

使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

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

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72