溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

如何進(jìn)行Java NIO中緩沖區(qū)的分析

發(fā)布時(shí)間:2021-12-03 17:32:38 來(lái)源:億速云 閱讀:100 作者:柒染 欄目:云計(jì)算

本篇文章為大家展示了如何進(jìn)行Java NIO中緩沖區(qū)的分析,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

對(duì)于NIO中緩沖區(qū)來(lái)說(shuō),還有很多的內(nèi)容值的學(xué)習(xí),如緩沖區(qū)的分片與數(shù)據(jù)共享,只讀緩沖區(qū)等。下面我們來(lái)看一下緩沖區(qū)一些更細(xì)節(jié)的內(nèi)容。

緩沖區(qū)的分配

在前面的幾個(gè)例子中,我們已經(jīng)看過(guò)了,在創(chuàng)建一個(gè)緩沖區(qū)對(duì)象時(shí),會(huì)調(diào)用靜態(tài)方法allocate()來(lái)指定緩沖區(qū)的容量,其實(shí)調(diào)用 allocate()相當(dāng)于創(chuàng)建了一個(gè)指定大小的數(shù)組,并把它包裝為緩沖區(qū)對(duì)象?;蛘呶覀円部梢灾苯訉⒁粋€(gè)現(xiàn)有的數(shù)組,包裝為緩沖區(qū)對(duì)象,如下示例代碼所示:

[java] view plain copy

 print?

  1. public class BufferWrap {  

  2.   

  3.     public void myMethod()  

  4.     {  

  5.         // 分配指定大小的緩沖區(qū)  

  6.         ByteBuffer buffer1 = ByteBuffer.allocate(10);  

  7.           

  8.         // 包裝一個(gè)現(xiàn)有的數(shù)組  

  9.         byte array[] = new byte[10];  

  10.         ByteBuffer buffer2 = ByteBuffer.wrap( array );  

  11.     }  

  12. }  

緩沖區(qū)分片

在NIO中,除了可以分配或者包裝一個(gè)緩沖區(qū)對(duì)象外,還可以根據(jù)現(xiàn)有的緩沖區(qū)對(duì)象來(lái)創(chuàng)建一個(gè)子緩沖區(qū),即在現(xiàn)有緩沖區(qū)上切出一片來(lái)作為一個(gè)新的緩沖區(qū),但現(xiàn)有的緩沖區(qū)與創(chuàng)建的子緩沖區(qū)在底層數(shù)組層面上是數(shù)據(jù)共享的,也就是說(shuō),子緩沖區(qū)相當(dāng)于是現(xiàn)有緩沖區(qū)的一個(gè)視圖窗口。調(diào)用slice()方法可以創(chuàng)建一個(gè)子緩沖區(qū),讓我們通過(guò)例子來(lái)看一下:

[java] view plain copy

 print?

  1. import java.nio.*;  

  2.   

  3. public class Program {  

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

  5.         ByteBuffer buffer = ByteBuffer.allocate( 10 );  

  6.           

  7.         // 緩沖區(qū)中的數(shù)據(jù)0-9  

  8.         for (int i=0; i<buffer.capacity(); ++i) {  

  9.             buffer.put( (byte)i );  

  10.         }  

  11.           

  12.         // 創(chuàng)建子緩沖區(qū)  

  13.         buffer.position( 3 );  

  14.         buffer.limit( 7 );  

  15.         ByteBuffer slice = buffer.slice();  

  16.           

  17.         // 改變子緩沖區(qū)的內(nèi)容  

  18.         for (int i=0; i<slice.capacity(); ++i) {  

  19.             byte b = slice.get( i );  

  20.             b *= 10;  

  21.             slice.put( i, b );  

  22.         }  

  23.           

  24.         buffer.position( 0 );  

  25.         buffer.limit( buffer.capacity() );  

  26.           

  27.         while (buffer.remaining()>0) {  

  28.             System.out.println( buffer.get() );  

  29.         }  

  30.     }  

  31. }  

在該示例中,分配了一個(gè)容量大小為10的緩沖區(qū),并在其中放入了數(shù)據(jù)0-9,而在該緩沖區(qū)基礎(chǔ)之上又創(chuàng)建了一個(gè)子緩沖區(qū),并改變子緩沖區(qū)中的內(nèi)容,從最后輸出的結(jié)果來(lái)看,只有子緩沖區(qū)“可見(jiàn)的”那部分?jǐn)?shù)據(jù)發(fā)生了變化,并且說(shuō)明子緩沖區(qū)與原緩沖區(qū)是數(shù)據(jù)共享的。

只讀緩沖區(qū)

只讀緩沖區(qū)非常簡(jiǎn)單,可以讀取它們,但是不能向它們寫(xiě)入數(shù)據(jù)??梢酝ㄟ^(guò)調(diào)用緩沖區(qū)的asReadOnlyBuffer()方法,將任何常規(guī)緩沖區(qū)轉(zhuǎn) 換為只讀緩沖區(qū),這個(gè)方法返回一個(gè)與原緩沖區(qū)完全相同的緩沖區(qū),并與原緩沖區(qū)共享數(shù)據(jù),只不過(guò)它是只讀的。如果原緩沖區(qū)的內(nèi)容發(fā)生了變化,只讀緩沖區(qū)的內(nèi)容也隨之發(fā)生變化:

[java] view plain copy

 print?

  1. import java.nio.*;  

  2.   

  3. public class Program {  

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

  5.         ByteBuffer buffer = ByteBuffer.allocate( 10 );  

  6.           

  7.         // 緩沖區(qū)中的數(shù)據(jù)0-9  

  8.         for (int i=0; i<buffer.capacity(); ++i) {  

  9.             buffer.put( (byte)i );  

  10.         }  

  11.   

  12.         // 創(chuàng)建只讀緩沖區(qū)  

  13.         ByteBuffer readonly = buffer.asReadOnlyBuffer();  

  14.           

  15.         // 改變?cè)彌_區(qū)的內(nèi)容  

  16.         for (int i=0; i<buffer.capacity(); ++i) {  

  17.             byte b = buffer.get( i );  

  18.             b *= 10;  

  19.             buffer.put( i, b );  

  20.         }  

  21.           

  22.         readonly.position(0);  

  23.         readonly.limit(buffer.capacity());  

  24.           

  25.         // 只讀緩沖區(qū)的內(nèi)容也隨之改變  

  26.         while (readonly.remaining()>0) {  

  27.             System.out.println( readonly.get());  

  28.         }  

  29.     }  

  30. }  

如果嘗試修改只讀緩沖區(qū)的內(nèi)容,則會(huì)報(bào)ReadOnlyBufferException異常。只讀緩沖區(qū)對(duì)于保護(hù)數(shù)據(jù)很有用。在將緩沖區(qū)傳遞給某個(gè) 對(duì)象的方法時(shí),無(wú)法知道這個(gè)方法是否會(huì)修改緩沖區(qū)中的數(shù)據(jù)。創(chuàng)建一個(gè)只讀的緩沖區(qū)可以保證該緩沖區(qū)不會(huì)被修改。只可以把常規(guī)緩沖區(qū)轉(zhuǎn)換為只讀緩沖區(qū),而不能將只讀的緩沖區(qū)轉(zhuǎn)換為可寫(xiě)的緩沖區(qū)。

直接緩沖區(qū)

直接緩沖區(qū)是為加快I/O速度,使用一種特殊方式為其分配內(nèi)存的緩沖區(qū),JDK文檔中的描述為:給定一個(gè)直接字節(jié)緩沖區(qū),Java虛擬機(jī)將盡最大努 力直接對(duì)它執(zhí)行本機(jī)I/O操作。也就是說(shuō),它會(huì)在每一次調(diào)用底層操作系統(tǒng)的本機(jī)I/O操作之前(或之后),嘗試避免將緩沖區(qū)的內(nèi)容拷貝到一個(gè)中間緩沖區(qū)中 或者從一個(gè)中間緩沖區(qū)中拷貝數(shù)據(jù)。要分配直接緩沖區(qū),需要調(diào)用allocateDirect()方法,而不是allocate()方法,使用方式與普通緩沖區(qū)并無(wú)區(qū)別,如下面的拷貝文件示例:

[java] view plain copy

 print?

  1. import java.io.*;  

  2. import java.nio.*;  

  3. import java.nio.channels.*;  

  4.   

  5. public class Program {  

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

  7.         String infile = "c:\\test.txt";  

  8.         FileInputStream fin = new FileInputStream( infile );  

  9.         FileChannel fcin = fin.getChannel();  

  10.           

  11.         String outfile = String.format("c:\\testcopy.txt");  

  12.         FileOutputStream fout = new FileOutputStream( outfile );      

  13.         FileChannel fcout = fout.getChannel();  

  14.           

  15.         // 使用allocateDirect,而不是allocate  

  16.         ByteBuffer buffer = ByteBuffer.allocateDirect( 1024 );  

  17.           

  18.         while (true) {  

  19.             buffer.clear();  

  20.               

  21.             int r = fcin.read( buffer );  

  22.               

  23.             if (r==-1) {  

  24.                 break;  

  25.             }  

  26.               

  27.             buffer.flip();  

  28.               

  29.             fcout.write( buffer );  

  30.         }  

  31.     }  

  32. }  

內(nèi)存映射文件I/O

內(nèi)存映射文件I/O是一種讀和寫(xiě)文件數(shù)據(jù)的方法,它可以比常規(guī)的基于流或者基于通道的I/O快的多。內(nèi)存映射文件I/O是通過(guò)使文件中的數(shù)據(jù)出現(xiàn)為 內(nèi)存數(shù)組的內(nèi)容來(lái)完成的,這其初聽(tīng)起來(lái)似乎不過(guò)就是將整個(gè)文件讀到內(nèi)存中,但是事實(shí)上并不是這樣。一般來(lái)說(shuō),只有文件中實(shí)際讀取或者寫(xiě)入的部分才會(huì)映射到內(nèi)存中。如下面的示例代碼:

[java] view plain copy

 print?

  1. import java.io.*;  

  2. import java.nio.*;  

  3. import java.nio.channels.*;  

  4.   

  5. public class Program {  

  6.     static private final int start = 0;<span >  

  7.     static private final int size = 1024;  

  8.       

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

  10.         RandomAccessFile raf = new RandomAccessFile( "c:\\test.txt", "rw" );  

  11.         FileChannel fc = raf.getChannel();  

  12.           

  13.         MappedByteBuffer mbb = fc.map( FileChannel.MapMode.READ_WRITE,  

  14.           start, size );  

  15.           

  16.         mbb.put( 0, (byte)97 );  

  17.         mbb.put( 1023, (byte)122 );  

  18.           

  19.         raf.close();  

  20.     }  

  21. }</span>  

上述內(nèi)容就是如何進(jìn)行Java NIO中緩沖區(qū)的分析,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI