使用Java中的FileChannel和ByteBuffer在文件中读取/写入文件
過去,我討論過RandomAccessFile以及如何將其用于在Java中進行更快的IO,在本Java NIO教程中,我們將了解如何通過使用FileChannel和ByteBuffer來使用讀/寫數據。
Channel提供了一種從文件讀取數據的替代方法,它提供了比InputStream或OutputStream更好的性能。 也可以在阻止和非阻止模式下打開它。 盡管FileChannles是讀/寫通道,但它們始終處于阻塞狀態 ,不能將它們置于非阻塞模式。 RandomAccessFile類將文件視為字節數組。
您可以將數據寫入Array的任何位置,也可以從任何位置讀取。 為此,它使用保存當前位置的指針,并提供諸如seek()幾種方法來移動該指針。 一旦定位正確,就可以從RandomAccessFile獲取FileChannel并開始從文件中讀取數據。 順便說一下,JDK 7還引入了NIO 2,它使處理文件和目錄變得更加容易。 閱讀Anghel Leonard的Pro Java 7 NIO.2以了解更多信息。
如何使用FileChannel和ByteBuffer讀取/寫入文件
在開始編碼之前,讓我們修改Java NIO中Channel和Buffer的基本概念。 一言以蔽之,緩沖區與通道一起工作。 通道是傳輸數據的管道,緩沖區是這些數據傳輸的源和目標。 在寫入的情況下,要寫入的數據放置在緩沖區中,該緩沖區傳遞到通道,而不是通道從緩沖區讀取該數據并寫入文件。
同樣,在讀取的情況下,通道會將數據放入您從文件 , 網絡或任何其他來源提供的緩沖區中。 由于相同的緩沖區用于讀取和寫入,即您將數據寫入緩沖區,而通道將其讀取以寫入文件,因此,一旦完成寫入緩沖區,就必須調用flip()方法。 flip()方法更改指針,并允許您從緩沖區讀取數據。 Java中的緩沖區有三種類型, 直接緩沖區,非直接緩沖區和映射緩沖區 。 在此示例中,我們將使用直接字節緩沖區。
使用FileChannel和Buffer讀取/寫入數據的步驟
這是逐步指南,開始使用RandomAccessFile , FileChannel和ByteBuffer從文件讀取數據:
要注意的另一個重要點是,您可以使用相同的緩沖區進行讀寫,但是需要翻轉它。 現在,讓我們看一個示例Java程序,該程序使用Java中的FileChannel和ByteBuffer從文件讀取/寫入數據。 在Memory Mapped File之后 ,這是從Java中讀取和寫入文件的第二快的方法。
Java程序,使用FileChannel和ByteBuffer從文件讀取/寫入
這是示例程序,以演示如何使用FileChannel和ByteBuffer類從文件(可以是二進制文件或文本文件)讀取和寫入數據。 我還使用抽象來創建一個名為Persistable的接口,該接口提供了兩種方法persist()和recover() 。 任何實現此接口的對象都可以保存和加載,但是如何保存和加載它們則留給實現者,例如,可以像我們一樣使用Chanel和Buffer,也可以使用舊方法在Java中讀取/寫入文件。 。
import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel;/*** Java Program to read and write on RandomAccessFile in Java* using FileChannle and ByteBuffer.** @author Javin*/ public class FileChannelDemo {public static void main(String args[]) {Tablet ipad = new Tablet("Apple", true, 1000);System.out.println("Writing into RandomAcessFile : " + ipad);write("tablet.store", ipad);Tablet fromStore = new Tablet();read("tablet.store", fromStore);System.out.println("Object read from RandomAcessFile : " + fromStore);}/** Method to write data into File using FileChannel and ByteBuffeer*/public static void write(String filename, Persistable object) {try {// Creating RandomAccessFile for writingRandomAccessFile store = new RandomAccessFile("tablet", "rw");// getting FileChannel from fileFileChannel channel = store.getChannel();// creating and initializing ByteBuffer for reading/writing dataByteBuffer buffer = ByteBuffer.allocate(2048);// an instance of Persistable writing into ByteBufferobject.persist(buffer);// flip the buffer for writing into filebuffer.flip();int numOfBytesWritten = channel.write(buffer); // writing into FileSystem.out.println("number of bytes written : " + numOfBytesWritten);channel.close(); // closing file channelstore.close(); // closing RandomAccess file} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/** Method to read data from File using FileChannel and ByteBuffeer*/public static void read(String filename, Persistable object) {try {// Opening RandomAccessFile for reading dataRandomAccessFile store = new RandomAccessFile("tablet", "rw");// getting file channelFileChannel channel = store.getChannel();// preparing buffer to read data from fileByteBuffer buffer = ByteBuffer.allocate(1024);// reading data from file channel into bufferint numOfBytesRead = channel.read(buffer);System.out.println("number of bytes read : " + numOfBytesRead);// You need to filp the byte buffer before readingbuffer.flip();// Recovering objectobject.recover(buffer);channel.close();store.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}} }我們的界面為抽象的讀寫機制。 這也是提供抽象的接口的實際用法 ,將要做的事情與要做的事情分開。 像這個界面,只說堅持并恢復,不說你怎么做。
interface Persistable {public void persist(ByteBuffer buffer);public void recover(ByteBuffer buffer); }實現Persistable使其可讀寫的具體類:
class Tablet implements Persistable {private String brand;private boolean isCellular;private long cost; // in US Dollarspublic Tablet() {brand = "";}public Tablet(String brand, boolean isCellular, long cost) {this.brand = brand;this.isCellular = isCellular;this.cost = cost;}public final String getBrand() {return brand;}public final boolean isCellular() {return isCellular;}public final long getCost() {return cost;}public final void setBrand(String brand) {this.brand = brand;}public final void setCellular(boolean isCellular) {this.isCellular = isCellular;}public final void setCost(long cost) {this.cost = cost;}@Overridepublic void persist(ByteBuffer buffer) {byte[] strBytes = brand.getBytes();buffer.putInt(strBytes.length);buffer.put(strBytes, 0, strBytes.length);buffer.put(isCellular == true ? (byte) 1 : (byte) 0);buffer.putLong(cost);}@Overridepublic void recover(ByteBuffer buffer) {int size = buffer.getInt();byte[] rawBytes = new byte[size];buffer.get(rawBytes, 0, size);this.brand = new String(rawBytes);this.isCellular = buffer.get() == 1 ? true : false;this.cost = buffer.getLong();}@Overridepublic String toString() {return "Tablet [brand=" + brand + ", isCellular=" + isCellular + ", cost=" + cost + "]";}}Output: Writing into RandomAcessFile : Tablet [brand=Apple, isCellular=true, cost=1000] number of bytes written : 18 number of bytes read : 1024 Object read from RandomAcessFile : Tablet [brand=Apple, isCellular=true, cost=1000]警告
將對象的內容寫入其中后,不要忘記翻轉字節緩沖區,因為文件通道需要讀取它才能將數據寫入RandomAccessFile。 如果忘記在調用FileChannel.write()之前先調用flip()方法,那么最終將什么都沒有寫入文件中。
同樣,將數據從文件讀入緩沖區后,請再次翻轉它,以便可以將數據從緩沖區讀到對象的常用內容。 許多Java程序員都會犯這樣的錯誤,即寫后不會翻轉,并最終導致調試時間過長,因為要么什么都沒有寫到文件中,要么什么都無法從文件中讀取。
這就是如何在Java中使用FileChannel和ByteBuffer讀取/寫入文件的全部內容。 在本演示中,我向您展示了如何使用FileChannel和ByteBuffer讀寫RandomAccessFile,但是您可以應用相同的技術從Java程序讀取任何其他文本或二進制文件。
翻譯自: https://www.javacodegeeks.com/2016/01/readingwriting-tofrom-files-using-filechannel-bytebuffer-java.html
總結
以上是生活随笔為你收集整理的使用Java中的FileChannel和ByteBuffer在文件中读取/写入文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 环评备案证明或环评报告(环评备案证)
- 下一篇: celine是什么档次(是一线奢侈品吗)