通道是數(shù)據(jù)源和Java程序之間的開放連接,用于執(zhí)行I/O操作。
Channel接口在java.nio.channels包中。
通道接口只聲明了兩個方法:close()和isOpen()。
ReadableByteChannel用于使用read()方法將數(shù)據(jù)從數(shù)據(jù)源讀取到字節(jié)緩沖區(qū)中。 WritableByteChannel用于使用write()方法將數(shù)據(jù)從字節(jié)緩沖區(qū)寫入數(shù)據(jù)宿。
ByteChannel能夠分別使用read()和write()方法讀取和寫入字節(jié)數(shù)據(jù)。
ScatteringByteChannel將數(shù)據(jù)從數(shù)據(jù)源讀取到多個字節(jié)緩沖區(qū)中。從已知的文件格式或類似的數(shù)據(jù)源讀取數(shù)據(jù)是有用的,其中在一些固定長度的報頭中提供數(shù)據(jù),隨后是可變長度的主體。
GatheringByteChannel從多個字節(jié)緩沖區(qū)中寫出數(shù)據(jù)。
要獲得一個通道,使用舊的方式使用java.io包中的類使用I/O創(chuàng)建InputStream和OutputStream的對象。
java.nio.channels包中的Channels類是一個實用程序類,它有許多靜態(tài)方法將流轉(zhuǎn)換為通道,反之亦然。
Channels類還提供了將讀寫器轉(zhuǎn)換為通道的方法,反之亦然。
例如,如果我們有一個名為myInputStream的輸入流對象,我們可以獲得一個ReadableByteChannel如下:
ReadableByteChannel rbc = Channels.newChannel(myInputStream);
如果我們有一個名為rbc的ReadableByteChannel,我們可以獲得如下的基本InputStream對象:
InputStream myInputStream = Channels.newInputStream(rbc);
FileInputStream和FileOutputStream類有一個稱為getChannel()的新方法來返回一個FileChannel對象。
FileChannel用于讀取和寫入數(shù)據(jù)到文件。
從FileInputStream獲取的FileChannel對象以只讀模式打開。
FileInputStream fis = new FileInputStream("test1.txt"); FileChannel fcReadOnly = fis.getChannel(); // A read-only channel
從FileOutputStream對象獲取的FileChannel對象以只寫模式打開。
FileOutputStream fos = new FileOutputStream("test1.txt"); FileChannel fcWriteOnly = fos.getChannel(); // A write-only channel以下代碼為不同種類的文件流獲取FileChannel對象:
// read-only mode RandomAccessFile raf1 = new RandomAccessFile("test1.txt", "r"); FileChannel rafReadOnly = raf1.getChannel(); // A read-only channel // read-write mode RandomAccessFile raf2 = new RandomAccessFile("test1.txt", "rw"); FileChannel rafReadWrite = raf2.getChannel(); // A read-write channel
FileChannel對象維護(hù)位置變量作為緩沖區(qū)。
FileChannel的read()和write()方法有兩種類型:相對位置讀/寫和絕對位置讀/寫。
當(dāng)我們打開一個FileChannel時,它的位置設(shè)置為0,這是文件的開始。
當(dāng)我們使用相對read()方法從FileChannel讀取時,它的位置增加讀取的字節(jié)數(shù)。
從FileChannel讀取的絕對位置不會影響其位置。
我們可以使用position()方法獲取FileChannel對象的當(dāng)前位置值。
我們可以使用位置(int newPosition)方法將其位置設(shè)置為新位置。
通道也是可自動關(guān)閉的。如果我們使用try-with-resources語句來獲取一個通道,那么通道將被自動關(guān)閉,這樣就避免了我們明確地調(diào)用通道的close()方法。
以下代碼從名為test1.txt的文件中讀取文本。
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class Main { public static void main(String[] args) { File inputFile = new File("test1.txt"); if (!inputFile.exists()) { System.out.println("The input file " + inputFile.getAbsolutePath() + " does not exist."); System.out.println("Aborted the file reading process."); return; } try (FileChannel fileChannel = new FileInputStream(inputFile).getChannel()) { ByteBuffer buffer = ByteBuffer.allocate(1024); while (fileChannel.read(buffer) > 0) { buffer.flip(); while (buffer.hasRemaining()) { byte b = buffer.get(); System.out.print((char) b); } buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } } }
上面的代碼生成以下結(jié)果。
以下代碼顯示如何使用緩沖區(qū)和通道寫入文件。
import java.io.File; import java.nio.channels.FileChannel; import java.io.IOException; import java.nio.ByteBuffer; import java.io.FileOutputStream; public class Main { public static void main(String[] args) { File outputFile = new File("test.txt"); try (FileChannel fileChannel = new FileOutputStream(outputFile) .getChannel()) { String text = getText(); byte[] byteData = text.toString().getBytes("UTF-8"); ByteBuffer buffer = ByteBuffer.wrap(byteData); fileChannel.write(buffer); } catch (IOException e1) { e1.printStackTrace(); } } public static String getText() { String lineSeparator = System.getProperty("line.separator"); StringBuilder sb = new StringBuilder(); sb.append("test"); sb.append(lineSeparator); sb.append("test"); sb.append(lineSeparator); sb.append("test"); sb.append(lineSeparator); sb.append("test"); return sb.toString(); } }
我們可以使用緩沖區(qū)和通道來復(fù)制文件。
獲取源文件和目標(biāo)文件的FileChannel對象,并對源FileChannel對象調(diào)用transferTo()方法或調(diào)用目標(biāo)FileChannel對象上的transferFrom()方法。
以下代碼顯示如何復(fù)制文件。
import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.channels.FileChannel; public class Main { public static void main(String[] args) throws Exception { FileChannel sourceChannel = new FileInputStream("sourceFile").getChannel(); FileChannel sinkChannel = new FileOutputStream("newFile").getChannel(); // Copy source file contents to the sink file sourceChannel.transferTo(0, sourceChannel.size(), sinkChannel); } }
更多建議: