Java NIO 教程(十六) Java NIO AsynchronousFileChannel

原文地址

目錄

在Java 7中盛末,AsynchronousFileChannel被添加到Java NIO。AsynchronousFileChannel使讀取數(shù)據(jù)丁溅,并異步地將數(shù)據(jù)寫入文件成為可能附井。本教程將解釋如何使用AsynchronousFileChannel重归。

創(chuàng)建一個AsynchronousFileChannel

您可以通過它的靜態(tài)方法open()創(chuàng)建一個AsynchronousFileChannel。下面是創(chuàng)建AsynchronousFileChannel的示例:

Path path = Paths.get("data/test.xml");

AsynchronousFileChannel fileChannel =
    AsynchronousFileChannel.open(path, StandardOpenOption.READ);

open()方法的第一個參數(shù)是指向與AsynchronousFileChannel相關聯(lián)的文件的Path實例。

第二個參數(shù)是一個或多個打開選項蛇更,它告訴AsynchronousFileChannel在底層文件上執(zhí)行哪些操作闺鲸。在本例中筋讨,我們使用了StandardOpenOption.READ選項。閱讀意味著該文件將被打開以供閱讀摸恍。

讀取數(shù)據(jù)

您可以通過兩種方式從AsynchronousFileChannel讀取數(shù)據(jù)悉罕。讀取數(shù)據(jù)的每一種方法都調用AsynchronousFileChannelread()方法之一。這兩種讀取數(shù)據(jù)的方法都將在下面的部分中介紹立镶。

通過Future閱讀數(shù)據(jù)

AsynchronousFileChannel讀取數(shù)據(jù)的第一種方法是調用返回Future的read()方法壁袄。下面是如何調用這個read()方法的示例:

Future<Integer> operation = fileChannel.read(buffer, 0);

read()方法的這個版本將ByteBuffer作為第一個參數(shù)。從AsynchronousFileChannel讀取的數(shù)據(jù)被讀入這個ByteBuffer媚媒。第二個參數(shù)是文件中的字節(jié)位置嗜逻,以便開始讀取。

read()方法會立即返回缭召,即使讀操作還沒有完成栈顷。通過調用read()方法返回的Future實例的isDone()方法,您可以檢查讀取操作是否完成嵌巷。

下面是一個更長的示例萄凤,展示如何使用read()方法的這個版本:

AsynchronousFileChannel fileChannel = 
    AsynchronousFileChannel.open(path, StandardOpenOption.READ);

ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;

Future<Integer> operation = fileChannel.read(buffer, position);

while(!operation.isDone());

buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
System.out.println(new String(data));
buffer.clear();

這個例子創(chuàng)建了一個AsynchronousFileChannel,然后創(chuàng)建一個ByteBuffer搪哪,它被傳遞給read()方法作為參數(shù)靡努,以及一個0的位置。在調用read()之后,這個示例循環(huán)惑朦,直到返回的isDone()方法返回true神年。當然,這不是非常有效地使用CPU行嗤,但是您需要等到讀取操作完成之后才會執(zhí)行已日。

讀取操作完成后,數(shù)據(jù)讀取到ByteBuffer中栅屏,然后進入一個字符串并打印到System.out中飘千。

通過一個CompletionHandler讀取數(shù)據(jù)

AsynchronousFileChannel讀取數(shù)據(jù)的第二種方法是調用read()方法版本,該方法將一個CompletionHandler作為參數(shù)栈雳。下面是如何調用read()方法:

fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {
    @Override
    public void completed(Integer result, ByteBuffer attachment) {
        System.out.println("result = " + result);

        attachment.flip();
        byte[] data = new byte[attachment.limit()];
        attachment.get(data);
        System.out.println(new String(data));
        attachment.clear();
    }

    @Override
    public void failed(Throwable exc, ByteBuffer attachment) {

    }
});

一旦讀取操作完成护奈,將調用CompletionHandlercompleted()方法。對于completed()方法的參數(shù)傳遞一個整數(shù)哥纫,它告訴我們讀取了多少字節(jié)霉旗,以及傳遞給read()方法的“附件”≈В“附件”是read()方法的第三個參數(shù)厌秒。在本例中,它是ByteBuffer擅憔,數(shù)據(jù)也被讀取鸵闪。您可以自由選擇要附加的對象。

如果讀取操作失敗暑诸,則將調用CompletionHandlerfailed()方法蚌讼。

寫數(shù)據(jù)

就像閱讀一樣,您可以通過兩種方式將數(shù)據(jù)寫入一個AsynchronousFileChannel个榕。寫入數(shù)據(jù)的每一種方法都調用異步文件通道的write()方法之一篡石。這兩種方法都將在下面的部分中介紹。

通過Future寫數(shù)據(jù)

AsynchronousFileChannel還允許您異步地寫數(shù)據(jù)西采。下面是一個完整的Java AsynchronousFileChannel示例:

Path path = Paths.get("data/test-write.txt");
AsynchronousFileChannel fileChannel = 
    AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);

ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;

buffer.put("test data".getBytes());
buffer.flip();

Future<Integer> operation = fileChannel.write(buffer, position);
buffer.clear();

while(!operation.isDone());

System.out.println("Write done");

首先凰萨,AsynchronousFileChannel以寫模式打開。然后創(chuàng)建一個ByteBuffer苛让,并將一些數(shù)據(jù)寫入其中沟蔑。然后,ByteBuffer中的數(shù)據(jù)被寫入到文件中狱杰。最后瘦材,示例檢查返回的Future,以查看寫操作完成時的情況仿畸。

注意食棕,在此代碼生效之前朗和,文件必須已經存在。如果該文件不存在簿晓,那么write()方法將拋出一個java.nio.file.NoSuchFileException眶拉。

您可以確保該Path指向的文件具有以下代碼:

if(!Files.exists(path)){
    Files.createFile(path);
}

通過一個CompletionHandler寫入數(shù)據(jù)

您還可以使用一個CompletionHandler將數(shù)據(jù)寫入到AsynchronousFileChannel中,以告訴您何時完成寫入憔儿,而不是Future忆植。下面是一個將數(shù)據(jù)寫入到AsynchronousFileChannel的示例,該通道有一個CompletionHandler:

Path path = Paths.get("data/test-write.txt");
if(!Files.exists(path)){
    Files.createFile(path);
}
AsynchronousFileChannel fileChannel = 
    AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);

ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;

buffer.put("test data".getBytes());
buffer.flip();

fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {

    @Override
    public void completed(Integer result, ByteBuffer attachment) {
        System.out.println("bytes written: " + result);
    }

    @Override
    public void failed(Throwable exc, ByteBuffer attachment) {
        System.out.println("Write failed");
        exc.printStackTrace();
    }
});

當寫操作完成時谒臼,將會調用CompletionHandlercompleted()方法朝刊。如果由于某種原因而寫失敗,則會調用failed()方法蜈缤。

注意如何將ByteBuffer用作附件——該對象被傳遞給CompletionHandler的方法拾氓。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市底哥,隨后出現(xiàn)的幾起案子咙鞍,更是在濱河造成了極大的恐慌,老刑警劉巖趾徽,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件续滋,死亡現(xiàn)場離奇詭異,居然都是意外死亡附较,警方通過查閱死者的電腦和手機吃粒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門潦俺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拒课,“玉大人,你說我怎么就攤上這事事示≡缦瘢” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵肖爵,是天一觀的道長卢鹦。 經常有香客問我,道長劝堪,這世上最難降的妖魔是什么冀自? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮秒啦,結果婚禮上熬粗,老公的妹妹穿的比我還像新娘。我一直安慰自己余境,他們只是感情好驻呐,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布灌诅。 她就那樣靜靜地躺著,像睡著了一般含末。 火紅的嫁衣襯著肌膚如雪猜拾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天佣盒,我揣著相機與錄音挎袜,去河邊找鬼。 笑死肥惭,一個胖子當著我的面吹牛宋雏,可吹牛的內容都是我干的。 我是一名探鬼主播务豺,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼磨总,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了笼沥?” 一聲冷哼從身側響起蚪燕,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奔浅,沒想到半個月后馆纳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡汹桦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年鲁驶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舞骆。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡钥弯,死狀恐怖,靈堂內的尸體忽然破棺而出督禽,到底是詐尸還是另有隱情脆霎,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布狈惫,位于F島的核電站睛蛛,受9級特大地震影響,放射性物質發(fā)生泄漏胧谈。R本人自食惡果不足惜忆肾,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菱肖。 院中可真熱鬧客冈,春花似錦、人聲如沸蔑滓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至燎窘,卻和暖如春摹闽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背褐健。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工付鹿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蚜迅。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓舵匾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谁不。 傳聞我的和親對象是個殘疾皇子坐梯,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內容