NIO入门系列之第3章:从理论到实践:NIO 中的读和写
3.1 ?概述
讀和寫是 I/O 的基本過程。從一個通道中讀取很簡單:只需創建一個緩沖區,然后讓通道將數據讀到這個緩沖區中。寫入也相當簡單:創建一個緩沖區,用數據填充它,然后讓通道用這些數據來執行寫入操作。
在本節中,我們將學習有關在Java 程序中讀取和寫入數據的一些知識。我們將回顧 NIO 的主要組件(緩沖區、通道和一些相關的方法),看看它們是如何交互以進行讀寫的。在接下來的幾節中,我們將更詳細地分析這其中的每個組件以及其交互。
3.2 ?從文件中讀取
在我們第一個練習中,我們將從一個文件中讀取一些數據。如果使用原來的 I/O,那么我們只需創建一個FileInputStream 并從它那里讀取。而在 NIO中,情況稍有不同:我們首先從FileInputStream 獲取一個FileInputStream 對象,然后使用這個通道來讀取數據。
在 NIO 系統中,任何時候執行一個讀操作,您都是從通道中讀取,但是您不是直接從通道讀取。因為所有數據最終都駐留在緩沖區中,所以您是從通道讀到緩沖區中。
因此讀取文件涉及三個步驟:(1)從FileInputStream 獲取 Channel,(2) 創建 Buffer,(3) 將數據從 Channel 讀到 Buffer 中。
現在,讓我們看一下這個過程。
3.3 ?三個容易的步驟
第一步是獲取通道。我們從 FileInputStream 獲取通道:
FileInputStream fin = new FileInputStream( "readandshow.txt" ); FileChannel fc = fin.getChannel();下一步是創建緩沖區:
ByteBuffer buffer = ByteBuffer.allocate( 1024 );最后,需要將數據從通道讀到緩沖區中,如下所示:
fc.read( buffer );
您會注意到,我們不需要告訴通道要讀多少數據到緩沖區中。每一個緩沖區都有復雜的內部統計機制,它會跟蹤已經讀了多少數據以及還有多少空間可以容納更多的數據。我們將在緩沖區內部細節中介紹更多關于緩沖區統計機制的內容。
// ReadAndShow package com.mzsx.nio; import java.io.*; import java.nio.*; import java.nio.channels.*; public class ReadAndShow {static public void main(String args[]) throws Exception {//創建FileInputStream實例FileInputStream fin = new FileInputStream("C:\\Users\\Qiang\\Desktop\\hydra.txt");//獲取通道FileChannel fc = fin.getChannel();//創建緩沖區ByteBuffer buffer = ByteBuffer.allocate(1024);//將數據從通道讀到緩沖區中fc.read(buffer);//反轉buffer.flip();int i = 0;while (buffer.remaining() > 0) {byte b = buffer.get();System.out.println("Character " + i + ": " + ((char) b)+" , buffer.remaining():"+buffer.remaining());i++;}fin.close();} }
3.4 ?寫入文件
在 NIO 中寫入文件類似于從文件中讀取。首先從 FileOutputStream 獲取一個通道:
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" ); FileChannel fc = fout.getChannel();
下一步是創建一個緩沖區并在其中放入一些數據- 在這里,數據將從一個名為message 的數組中取出,這個數組包含字符串"Some bytes" 的 ASCII 字節(本教程后面將會解釋buffer.flip() 和 buffer.put() 調用)。
ByteBuffer buffer = ByteBuffer.allocate( 1024 ); for (int i=0; i<message.length; ++i) {buffer.put( message[i] ); } buffer.flip();
最后一步是寫入緩沖區中:
fc.write( buffer );注意在這里同樣不需要告訴通道要寫入多數據。緩沖區的內部統計機制會跟蹤它包含多少數據以及還有多少數據要寫入。
// WriteSomeBytes package com.mzsx.nio; import java.io.*; import java.nio.*; import java.nio.channels.*; public class WriteSomeBytes {static private final byte message[] = { 83, 111, 109, 101, 32, 98, 121,116, 101, 115, 46 };static public void main(String args[]) throws Exception {//實例化FileOutputStreamFileOutputStream fout = new FileOutputStream("C:\\Users\\Qiang\\Desktop\\writesomebytes.txt");//獲取通道FileChannel fc = fout.getChannel();//獲取緩沖區ByteBuffer buffer = ByteBuffer.allocate(1024);//向緩沖區添加數據for (int i = 0; i < message.length; ++i) {buffer.put(message[i]);}buffer.flip();//寫入緩沖區fc.write(buffer);fout.close();} }3.5 ?讀寫結合
下面我們將看一下在結合讀和寫時會有什么情況。我們以一個名為 CopyFile.java 的簡單程序作為這個練習的基礎,它將一個文件的所有內容拷貝到另一個文件中。CopyFile.java 執行三個基本操作:首先創建一個 Buffer,然后從源文件中將數據讀到這個緩沖區中,然后將緩沖區寫入目標文件。這個程序不斷重復—讀、寫、讀、寫—直到源文件結束。
CopyFile 程序讓您看到我們如何檢查操作的狀態,以及如何使用 clear() 和 flip() 方法重設緩沖區,并準備緩沖區以便將新讀取的數據寫到另一個通道中。
3.6 ?運行 CopyFile 例子
實例讀寫結合:
// CopyFile import java.io.*; import java.nio.*; import java.nio.channels.*; public class CopyFile {static public void main(String args[]) throws Exception {//需要輸入源文件夾和目標文件的全路徑if (args.length < 2) {System.err.println("Usage: java CopyFile infile outfile");System.exit(1);}String infile = args[0];String outfile = args[1];FileInputStream fin = new FileInputStream(infile);FileOutputStream fout = new FileOutputStream(outfile);//獲得通道FileChannel fcin = fin.getChannel();FileChannel fcout = fout.getChannel();//創建緩沖區ByteBuffer buffer = ByteBuffer.allocate(1024);while (true) {//清空緩沖區buffer.clear();//將數據從通道讀到緩沖區中int r = fcin.read(buffer);//檢查狀態if (r == -1) {break;}//反轉buffer.flip();//寫入fcout.write(buffer);}fcin.close();fcout.close();fin.close();fout.close();} }因為緩沖區會跟蹤它自己的數據,所以CopyFile 程序的內部循環 (inner loop) 非常簡單,如下所示:
fcin.read( buffer ); fcout.write( buffer );
第一行將數據從輸入通道fcin 中讀入緩沖區,第二行將這些數據寫到輸出通道 fcout 。
3.7 ?檢查狀態
下一步是檢查拷貝何時完成。當沒有更多的數據時,拷貝就算完成,并且可以在 read() 方法返回 -1 是判斷這一點,如下所示:
int r = fcin.read( buffer ); if (r==-1) {break; }
3.8 ?重設緩沖區
最后,在從輸入通道讀入緩沖區之前,我們調用 clear() 方法。同樣,在將緩沖區寫入輸出通道之前,我們調用 flip() 方法,如下所示:
buffer.clear(); int r = fcin.read( buffer ); if (r==-1) {break; } buffer.flip(); fcout.write( buffer );
clear() 方法重設緩沖區,使它可以接受讀入的數據。 flip() 方法讓緩沖區可以將新讀入的數據寫入另一個通道。
轉載于:https://blog.51cto.com/qiangmzsx/1409546
總結
以上是生活随笔為你收集整理的NIO入门系列之第3章:从理论到实践:NIO 中的读和写的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MemoryMappingFile泄漏分
- 下一篇: 用户软件互评