真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯網站制作重慶分公司

JavaNIO-創(chuàng)新互聯

Java NIO

Java NIO簡介

Java NIO ( New IO )是從 Java 1.4 版本開始引入的一個新的 IO API ,
可以替代標準的 Java IO API 。NIO 與原來的 IO 有同樣的作用和目的,但是使用的方式完全不同, NIO 支持面向緩沖區(qū)的、基于通道的 IO 操作。 NIO 將以更加高效的方式進行文件的讀寫操作.

讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:主機域名、虛擬主機、營銷軟件、網站建設、泉州網站維護、網站推廣。

Java IO 與 NIO 的區(qū)別

IONIO
面向流(StreamOriented)面向緩沖區(qū)(BufferOriented)
阻塞IO(BlockingIO)非阻塞IO(NonBlockingIO)
(無)選擇器(Selectors)

通道(Channel)與緩沖區(qū)(Buffer)

Java NIO 系統(tǒng)的核心在于:通道 (Channel) 和緩沖區(qū)(Buffer) 。
通道表示打開到 IO 設備 ( 例如:文件、套接字 ) 的連接。若需要使用 NIO 系統(tǒng),需要獲取用于連接 IO 設備的通道以及用于容納數據的緩沖區(qū)。然后操作緩沖區(qū),對數據進行處理。
簡而言之, Channel 負責傳輸, Buffer 負責存儲

緩沖區(qū)(Buffer)

緩沖區(qū)( Buffer ):一個用于特定基本數據類型的容器。由 java.nio 包定義的,所有緩沖區(qū)都是 Buffer 抽象類的子類。
Java NIO 中的 Buffer 主要用于與 NIO 通道進行交互,數據是從通道讀入緩沖區(qū),從緩沖區(qū)寫入通道中的。
Buffer 就像一個數組,可以保存多個相同類型的數據。
根據數據類型不同 (boolean 除外 ) ,有以下 Buffer 常用子類:
ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
上述 Buffer 類 他們都采用相似的方法進行管理數據,只是各自
管理的數據類型不同而已。都是通過如下方法獲取一個 Buffer對象
static XxxBuffer allocate(int capacity) : 創(chuàng)建一個容量為 capacity 的 XxxBuffer 對象

緩沖區(qū)的基本屬性

Buffer 中的重要概念:

? 容量 (capacity) : 表示 Buffer 大數據容量,緩沖區(qū)容量不能為負,并且創(chuàng)
建后不能更改。

? 限制 (limit) : 第一個不應該讀取或寫入的數據的索引,即位于 limit 后的數據
不可讀寫。緩沖區(qū)的限制不能為負,并且不能大于其容量。

? 位置 (position) : 下一個要讀取或寫入的數據的索引。緩沖區(qū)的位置不能為
負,并且不能大于其限制

? 標記 (mark) 與重置 (reset) : 標記是一個索引,通過 Buffer 中的 mark() 方法
指定 Buffer 中一個特定的 position ,之后可以通過調用 reset() 方法恢復到這
個 position.
標記、位置、限制、容量遵守以下不變式:
0 <= mark <= position <= limit <= capacity

緩沖區(qū)的常用方法

緩沖區(qū)存取數據的兩個核心方法:

  • put() : 存入數據到緩沖區(qū)中
  • get() : 獲取緩沖區(qū)中的數據
  • flip(); 切換讀取數據模式
  • rewind() : 可重復讀
  • clear() : 清空緩沖區(qū). 但是緩沖區(qū)中的數據依然存在,但是處于“被遺忘”狀態(tài)
  • mark() : 標記是一個索引,通過 Buffer 中的 mark() 方法
    指定 Buffer 中一個特定的 position ,之后可以通過調用 reset() 方法恢復到這
    個 position.
    Java NIO

    列:

    public void test1(){
    String str = "abcde";

    //1. 分配一個指定大小的緩沖區(qū)
    ByteBuffer buf = ByteBuffer.allocate(1024);
    
    System.out.println("-----------------allocate()----------------");
    System.out.println(buf.position());
    System.out.println(buf.limit());
    System.out.println(buf.capacity());
    
    //2. 利用 put() 存入數據到緩沖區(qū)中
    buf.put(str.getBytes());
    
    System.out.println("-----------------put()----------------");
    System.out.println(buf.position());
    System.out.println(buf.limit());
    System.out.println(buf.capacity());
    
    //3. 切換讀取數據模式
    buf.flip();
    
    System.out.println("-----------------flip()----------------");
    System.out.println(buf.position());
    System.out.println(buf.limit());
    System.out.println(buf.capacity());
    
    //4. 利用 get() 讀取緩沖區(qū)中的數據
    byte[] dst = new byte[buf.limit()];
    buf.get(dst);
    System.out.println(new String(dst, 0, dst.length));
    
    System.out.println("-----------------get()----------------");
    System.out.println(buf.position());
    System.out.println(buf.limit());
    System.out.println(buf.capacity());
    
    //5. rewind() : 可重復讀
    buf.rewind();
    
    System.out.println("-----------------rewind()----------------");
    System.out.println(buf.position());
    System.out.println(buf.limit());
    System.out.println(buf.capacity());
    
    //6. clear() : 清空緩沖區(qū). 但是緩沖區(qū)中的數據依然存在,但是處于“被遺忘”狀態(tài)
    buf.clear();
    
    System.out.println("-----------------clear()----------------");
    System.out.println(buf.position());
    System.out.println(buf.limit());
    System.out.println(buf.capacity());
    
    System.out.println((char)buf.get());

    }

    Buffer的常用方法

方法描述
Buffer clear()清空緩沖區(qū)并返回對緩沖區(qū)的引用
Buffer flip()將緩沖區(qū)的界限設置為當前位置,并將當前位置充值為0
int capacity()返回Buffer的capacity大小
boolean hasRemaining()判斷緩沖區(qū)中是否還有元素
int limit()返回Buffer的界限(limit)的位置
Buffer limit(intn)將設置緩沖區(qū)界限為n,并返回一個具有新limit的緩沖區(qū)對象
Buffer mark()對緩沖區(qū)設置標記
int position()返回緩沖區(qū)的當前位置position
Buffer position(int n)將設置緩沖區(qū)的當前位置為n,并返回修改后的Buffer對象
int remaining()返回position和limit之間的元素個數
Buffer reset()將位置position轉到以前設置的mark所在的位置
Buffer rewind()將位置設為為0,取消設置的mark

緩沖區(qū)的數據操作

Buffer 所有子類提供了兩個用于數據操作的方法 get() 與 put() 方法

? 獲取 Buffer 中的數據
get() :讀取單個字節(jié)
get(byte[] dst) :批量讀取多個字節(jié)到 dst 中
get(int index) :讀取指定索引位置的字節(jié) ( 不會移動 position)
放入數據到 Buffer 中
put(byte b) :將給定單個字節(jié)寫入緩沖區(qū)的當前位置
put(byte[] src) :將 src 中的字節(jié)寫入緩沖區(qū)的當前位置
put(int index, byte b) :將指定字節(jié)寫入緩沖區(qū)的索引位置 ( 不會移動 position)

直接與非直接緩沖區(qū)

字節(jié)緩沖區(qū)要么是直接的,要么是非直接的。如果為直接字節(jié)緩沖區(qū),則 Java 虛擬機會盡大努力直接在
此緩沖區(qū)上執(zhí)行本機 I/O 操作。也就是說,在每次調用基礎操作系統(tǒng)的一個本機 I/O 操作之前(或之后),
虛擬機都會盡量避免將緩沖區(qū)的內容復制到中間緩沖區(qū)中(或從中間緩沖區(qū)中復制內容)。

直接字節(jié)緩沖區(qū)可以通過調用此類的 allocateDirect() 工廠方法 來創(chuàng)建。此方法返回的 緩沖區(qū)進行分配和取消
分配所需成本通常高于非直接緩沖區(qū) 。直接緩沖區(qū)的內容可以駐留在常規(guī)的垃圾回收堆之外,因此,它們對
應用程序的內存需求量造成的影響可能并不明顯。所以,建議將直接緩沖區(qū)主要分配給那些易受基礎系統(tǒng)的
本機 I/O 操作影響的大型、持久的緩沖區(qū)。一般情況下,最好僅在直接緩沖區(qū)能在程序性能方面帶來明顯好
處時分配它們。

直接字節(jié)緩沖區(qū)還可以通過 FileChannel 的 map() 方法 將文件區(qū)域直接映射到內存中來創(chuàng)建。該方法返回
MappedByteBuffer 。 Java 平臺的實現有助于通過 JNI 從本機代碼創(chuàng)建直接字節(jié)緩沖區(qū)。如果以上這些緩沖區(qū)中的某個緩沖區(qū)實例指的是不可訪問的內存區(qū)域,則試圖訪問該區(qū)域不會更改該緩沖區(qū)的內容,并且將會在
訪問期間或稍后的某個時間導致拋出不確定的異常。

字節(jié)緩沖區(qū)是直接緩沖區(qū)還是非直接緩沖區(qū)可通過調用其 isDirect() 方法來確定。提供此方法是為了能夠在
性能關鍵型代碼中執(zhí)行顯式緩沖區(qū)管理。

內存映射文件為什么效率高

文件i/o的讀操作,會先向文件設備發(fā)起讀請求,然后驅動把請求要讀的數據讀取到文件的緩沖區(qū)中,這個緩沖區(qū)位于內核,然后再把這個緩沖區(qū)中的數據復制到程序虛擬地址空間中的一塊區(qū)域中。

文件i/o的寫操作,會向文件設備發(fā)起寫請求,驅動把要寫入的數據復制到程序的緩沖區(qū)中,位于用戶空間,然后再把這個緩沖區(qū)的數據復制到文件的緩沖區(qū)中。

內存映射文件,是把位于硬盤中的文件看做是程序地址空間中一塊區(qū)域對應的物理存儲器,文件的數據就是這塊區(qū)域內存中對應的數據,讀寫文件中的數據,直接對這塊區(qū)域的地址操作,就可以,減少了內存復制的環(huán)節(jié)。

所以說,內存映射文件比起文件I/O操作,效率要高,而且文件越大,體現出來的差距越大。
Java NIO
Java NIO

通道(Channel)

通道( Channel ):由 java.nio.channels 包定義的。 Channel 表示 IO 源與目標打開的連接。
Channel 類似于傳統(tǒng)的“流”。只不過 Channel本身不能直接訪問數據, Channel 只能與Buffer 進行交互。
Java 為 Channel 接口提供的最主要實現類如下
本地文件傳輸通道
FileChannel :用于讀取、寫入、映射和操作文件的通道

網絡數據傳輸的通道
DatagramChannel :通過 UDP 讀寫網絡中的數據通道
SocketChannel :通過 TCP 讀寫網絡中的數據。
ServerSocketChannel :可以監(jiān)聽新進來的 TCP 連接,對每一個新進來的連接都會創(chuàng)建一個 SocketChannel
Java NIO
Java NIO
Java NIO

獲取通道

獲取通道的一種方式是對支持通道的對象調用
getChannel() 方法。支持通道的類如下:
本地I/O
FileInputStream
FileOutputStream
RandomAccessFile

網絡 I/O
DatagramSocket
Socket
ServerSocket

獲取通道的其他方式是使用 Files 類的靜態(tài)方法 newByteChannel() 獲取字節(jié)通道?;蛘咄ㄟ^通道的靜態(tài)方法 open() 打開并返回指定通道。
例如:
在 JDK 1.7 中的 NIO.2 針對各個通道提供了靜態(tài)方法 open()
//打開一個讀取的通道
FileChannel in = FileChannel.open(Paths.get("MyTest.java"), StandardOpenOption.READ);
//打開一個寫的通道
FileChannel out = FileChannel.open(Paths.get("MyTest.java"),StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
在 JDK 1.7 中的 NIO.2 的 Files 工具類的 newByteChannel()

通道的數據傳輸

將 Buffer 中數據寫入 Channel

例如:inChannel.read(byteBuffer)

從 Channel 讀取數據到 Buffer

例如:outChannel.write(byteBuffer);
列文件復制:
使用非直接緩沖區(qū):

public static void main(String[] args) throws IOException {
//創(chuàng)建文件輸入輸入流
FileInputStream in = new FileInputStream("短發(fā).mp3");
FileOutputStream out = new FileOutputStream("短發(fā)2.mp3");
//文件輸入輸入流的getChannel()方法獲取通道
FileChannel inChannel = in.getChannel();
FileChannel outChannel = out.getChannel();
//獲取非直接緩沖區(qū)
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//將通道中的數據放入到緩沖區(qū)中
while (inChannel.read(byteBuffer) != -1) {
//切換讀取數據的模式
byteBuffer.flip();
//將緩沖區(qū)中的數據寫入通道中
outChannel.write(byteBuffer);
//清空緩沖區(qū)
byteBuffer.clear();
}
//釋放資源
in.close();
out.close();
inChannel.close();
outChannel.close();
}

使用直接緩沖區(qū)

public static void main(String[] args) throws IOException {
//通過文件通道的靜態(tài)方法,打開讀寫通道
//參1:通過Paths獲取源文件的路徑
//參2:操作模式 StandardOpenOption.READ 讀取模式
//打開讀取文件的通道
FileChannel in = FileChannel.open(Paths.get("短發(fā).mp3"), StandardOpenOption.READ);
//打開寫入的通道 模式要讀還要寫 StandardOpenOption.CREATE 意思是文件不存在就創(chuàng)建,如果存在就覆蓋
//StandardOpenOption.CREATE_NEW 意思是文件不存在就創(chuàng)建,如果存在就報錯
FileChannel out = FileChannel.open(Paths.get("短發(fā)2.mp3"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
//操作內存映射文件(也就是這個緩沖區(qū)在物理內存中)
MappedByteBuffer inByteBuffer = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
MappedByteBuffer outByteBuffer = out.map(FileChannel.MapMode.READ_WRITE, 0, in.size());
//直接對緩沖區(qū)進行讀寫操作
byte[] bytes = new byte[inByteBuffer.limit()];
inByteBuffer.get(bytes);
outByteBuffer.put(bytes);
//釋放資源
in.close();
out.close();

}

通道之間的數據傳輸

通道之間的數據傳輸 用的也是直接緩沖區(qū)的方式

  • transferFrom()
  • transferTo()
    列:

public static void main(String[] args) throws IOException {
FileChannel in = FileChannel.open(Paths.get("E:\MyTest.txt"), StandardOpenOption.READ);
FileChannel out = FileChannel.open(Paths.get("D:\MyTestCopy.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
//in.transferTo(0,in.size(),out);//把數據讀到 輸出通道中取 完成文件的復制
//或者使用輸出通道
out.force(false);
out.transferFrom(in,0,in.size()); //寫出數據,寫出的數據從輸入通道中來
in.close();
out.close();

分散 (Scatter)和聚集(Gather)

分散讀?。?Scattering Reads )是指從 Channel 中讀取的數據“分散”到多個Buffer緩沖區(qū)中
Java NIO

注:按照緩沖區(qū)的順序,從Channel中讀取的數據依次將Buffer填滿。

聚集寫入( Gathering Writes )是指將多個 Buffer緩沖區(qū) 中的數據“聚集”到 Channel 。
Java NIO

注:按照緩沖區(qū)的順序,寫入position和limit之間的數據到Channel.
列:

public static void main(String[] args) throws IOException {
RandomAccessFile in = new RandomAccessFile("E:\demo.txt", "rw");
RandomAccessFile out = new RandomAccessFile("E:\democopy.txt", "rw");
//獲取讀取通道
FileChannel inChannel = in.getChannel();
//創(chuàng)建多個緩沖區(qū)
ByteBuffer buffer1 = ByteBuffer.allocate(100);
ByteBuffer buffer2 = ByteBuffer.allocate(1024);
//分散讀取到多個緩沖區(qū)中
ByteBuffer[] byteBuffers=new ByteBuffer[]{buffer1,buffer2};//把多個緩沖區(qū)放到一個大的數組中
long read = inChannel.read(byteBuffers);//把這個大的緩沖區(qū)傳進去

//當然我們可以看看,每個緩沖區(qū)中讀入的數據
    //byteBuffers[0].flip(); //切換到讀取模式 看一下第一個緩沖區(qū),讀入的100個字節(jié)
    //byte[] array = byteBuffers[0].array();//把ByteBuffer轉換成字節(jié)數組
    //String s = new String(array, 0, byteBuffers[0].limit());
    //System.out.println(s);

    //把每個緩沖區(qū),切換到讀取模式
    for (ByteBuffer buffer : byteBuffers) {
        buffer.flip();
    }
    //聚集寫入
    FileChannel outChannel = out.getChannel();
    outChannel.write(byteBuffers);

    //釋放資源
    inChannel.close();
    outChannel.close();
}

FileChannel 的常用方法

方法描述
int read(ByteBufferdst**)**從Channel中讀取數據到ByteBuffer
long read(ByteBuffer**[]dsts)**將Channel中的數據“分散”到ByteBuffer[]
int write(ByteBuffersrc**)**將ByteBuffer中的數據寫入到Channel
long write(ByteBuffer**[]srcs)**將ByteBuffer[]中的數據“聚集”到Channel
long position()返回此通道的文件位置
FileChannel position(long p)設置此通道的文件位置
long size()返回此通道的文件的當前大小
FileChannel truncate(long s)將此通道的文件截取為給定大小
void force(boolean metaData)強制將所有對此通道的文件更新寫入到存儲設備中

Files 類中復制文件的方法

static long copy(InputStream in, Path target, CopyOption... options)
將所有字節(jié)從輸入流復制到文件。

static long copy(Path source, OutputStream out)
將從文件到輸出流的所有字節(jié)復制到輸出流中。

static Path copy(Path source, Path target, CopyOption... options)
將一個文件復制到目標文件。

Files類中的常用方法

java.nio.file.Files 用于操作文件或目錄的工具類

Files 常用方法:

?    Path copy(Path src, Path dest, CopyOption … how) : 文件的復制

?    Path createDirectory(Path path, FileAttribute … attr) : 創(chuàng)建一個目錄

?    Path createFile(Path path, FileAttribute … arr) : 創(chuàng)建一個文件

?    void delete(Path path) : 刪除一個文件

?    Path move(Path src, Path dest, CopyOption…h(huán)ow) : 將 src 移動到 dest 位置

?    long size(Path path) : 返回 path 指定文件的大小

Files 常用方法:用于判斷
boolean exists(Path path, LinkOption … opts) : 判斷文件是否存在
boolean isDirectory(Path path, LinkOption … opts) : 判斷是否是目錄
boolean isExecutable(Path path) : 判斷是否是可執(zhí)行文件
boolean isHidden(Path path) : 判斷是否是隱藏文件
boolean isReadable(Path path) : 判斷文件是否可讀
boolean isWritable(Path path) : 判斷文件是否可寫
boolean notExists(Path path, LinkOption … opts) : 判斷文件是否不存在
public static A readAttributes(Path path,Class type,LinkOption...
options) : 獲取與 path 指定的文件相關聯的屬性。

Files 常用方法:用于操作內容
SeekableByteChannel newByteChannel(Path path, OpenOption…h(huán)ow) : 獲取與指定文件的連接,how 指定打開方式。
DirectoryStream newDirectoryStream(Path path) : 打開 path 指定的目錄
InputStream newInputStream(Path path, OpenOption…h(huán)ow): 獲取 InputStream 對象
OutputStream newOutputStream(Path path, OpenOption…h(huán)ow) : 獲取 OutputStream 對象

創(chuàng)新互聯www.cdcxhl.cn,專業(yè)提供香港、美國云服務器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網絡助力業(yè)務部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統(tǒng)配攻擊溯源,準確進行流量調度,確保服務器高可用性。佳節(jié)活動現已開啟,新人活動云服務器買多久送多久。


名稱欄目:JavaNIO-創(chuàng)新互聯
鏈接分享:
http://weahome.cn/article/csgiee.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部