-
Notifications
You must be signed in to change notification settings - Fork 1
/
15262259555946.html
571 lines (346 loc) · 20.9 KB
/
15262259555946.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
A Guide To NIO2 Asynchronous File Channel - Junkman
</title>
<link href="atom.xml" rel="alternate" title="Junkman" type="application/atom+xml">
<link rel="stylesheet" href="asset/css/foundation.min.css" />
<link rel="stylesheet" href="asset/css/docs.css" />
<script src="asset/js/vendor/modernizr.js"></script>
<script src="asset/js/vendor/jquery.js"></script>
<script src="asset/highlightjs/highlight.pack.js"></script>
<link href="asset/highlightjs/styles/github.css" media="screen, projection" rel="stylesheet" type="text/css">
<script>hljs.initHighlightingOnLoad();</script>
<script type="text/javascript">
function before_search(){
var searchVal = 'site:panlw.github.io ' + document.getElementById('search_input').value;
document.getElementById('search_q').value = searchVal;
return true;
}
</script>
</head>
<body class="antialiased hide-extras">
<div class="marketing off-canvas-wrap" data-offcanvas>
<div class="inner-wrap">
<nav class="top-bar docs-bar hide-for-small" data-topbar>
<section class="top-bar-section">
<div class="row">
<div style="position: relative;width:100%;"><div style="position: absolute; width:100%;">
<ul id="main-menu" class="left">
<li id=""><a target="self" href="index.html">Home</a></li>
<li id=""><a target="_self" href="archives.html">Archives</a></li>
</ul>
<ul class="right" id="search-wrap">
<li>
<form target="_blank" onsubmit="return before_search();" action="http://google.com/search" method="get">
<input type="hidden" id="search_q" name="q" value="" />
<input tabindex="1" type="search" id="search_input" placeholder="Search"/>
</form>
</li>
</ul>
</div></div>
</div>
</section>
</nav>
<nav class="tab-bar show-for-small">
<a href="javascript:void(0)" class="left-off-canvas-toggle menu-icon">
<span> Junkman</span>
</a>
</nav>
<aside class="left-off-canvas-menu">
<ul class="off-canvas-list">
<li><a href="index.html">HOME</a></li>
<li><a href="archives.html">Archives</a></li>
<li><a href="about.html">ABOUT</a></li>
<li><label>Categories</label></li>
<li><a href="Infra.html">Infra</a></li>
<li><a href="Coding.html">Coding</a></li>
<li><a href="Modeling.html">Modeling</a></li>
<li><a href="Archtecting.html">Archtecting</a></li>
</ul>
</aside>
<a class="exit-off-canvas" href="#"></a>
<section id="main-content" role="main" class="scroll-container">
<script type="text/javascript">
$(function(){
$('#menu_item_index').addClass('is_active');
});
</script>
<div class="row">
<div class="large-8 medium-8 columns">
<div class="markdown-body article-wrap">
<div class="article">
<h1>A Guide To NIO2 Asynchronous File Channel</h1>
<div class="read-more clearfix">
<span class="date">2018/5/13</span>
<span>posted in </span>
<span class="posted-in"><a href='Java.html'>Java</a></span>
<span class="comments">
</span>
</div>
</div><!-- article -->
<div class="article-content">
<blockquote>
<p><a href="http://www.baeldung.com/java-nio2-async-file-channel">http://www.baeldung.com/java-nio2-async-file-channel</a><br/>
Last modified: January 12, 2018</p>
</blockquote>
<h3 id="toc_0"><strong>I just announced the new <u>Spring 5</u> modules in REST With Spring:</strong></h3>
<h2 id="toc_1"><strong>1. Overview</strong></h2>
<p>In this article, we are going to explore one of the key additional APIs of the new I/O (NIO2) in Java 7, asynchronous file channel APIs.</p>
<p>If you are new to asynchronous channel APIs in general, we have an introductory article on this site which you can read by following <a href="/java-nio-2-async-channels">this link</a> before proceeding.</p>
<p>You can read more about NIO.2 <a href="/java-nio-2-file-api">file operations</a> and <a href="/java-nio-2-path">path operations</a> as well – understanding these will make this article much easier to follow.</p>
<p>To use the NIO2 asynchronous file channels in our projects, we have to import the <u>java.nio.channels</u> package as it bundles all required classes:</p>
<pre><code class="language-java">import java.nio.channels.*;
</code></pre>
<h2 id="toc_2"><strong>2. The <u>AsynchronousFileChannel</u></strong></h2>
<p>In this section, we will explore how to use the main class that enables us to perform asynchronous operations on files, the <u>AsynchronousFileChannel</u> class. To create an instance of it, we call the static <u>open</u> method:</p>
<pre><code class="language-java">Path filePath = Paths.get("/path/to/file");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
filePath, READ, WRITE, CREATE, DELETE_ON_CLOSE);
</code></pre>
<p>All enum values come from the Sta_ndardOpenOption_.</p>
<p>The first parameter to the open API is a <u>Path</u> object representing the file location. To read more about path operations in NIO2, follow <a href="/java-nio-2-path">this link</a>. The other parameters make up a set specifying options that should be available to the returned file channel.</p>
<p>The asynchronous file channel we have created can be used to perform all known operations on a file. To perform only a subset of the operations, we would specify options for only those. For instance, to only read:</p>
<pre><code class="language-java">Path filePath = Paths.get("/path/to/file");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
filePath, StandardOpenOption.READ);
</code></pre>
<h2 id="toc_3"><strong>3. Reading From a File</strong></h2>
<p>Just like with all asynchronous operations in NIO2, reading a file’s contents can be done in two ways. Using <u>Future</u> and using <u>CompletionHandler</u>. In each case, we use the <u>read</u> API of the returned channel.</p>
<p>Inside the test resources folder of maven or in the source directory if not using maven, let’s create a file called <u>file.txt</u> with only the text <u>baeldung.com</u> at it’s beginning. We will now demonstrate how to read this content.</p>
<h3 id="toc_4"><strong>3.1. The Future Approach</strong></h3>
<p>First, we will see how to read a file asynchronously using the <u>Future</u> class:</p>
<pre><code class="language-java">@Test
public void givenFilePath_whenReadsContentWithFuture_thenCorrect() {
Path path = Paths.get(
URI.create(
this.getClass().getResource("/file.txt").toString()));
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
path, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> operation = fileChannel.read(buffer, 0);
// run other code as operation continues in background
operation.get();
String fileContent = new String(buffer.array()).trim();
buffer.clear();
assertEquals(fileContent, "baeldung.com");
}
</code></pre>
<p>In the above code, after creating a file channel, we make use of the <u>read</u> API – which takes a <u>ByteBuffer</u> to store the content read from the channel as its first parameter.</p>
<p>The second parameter is a long indicating the position in the file from which to start reading.</p>
<p>The method returns right away whether the file has been read or not.</p>
<p>Next, we can execute any other code as the operation continues in the background. When we are done with executing other code, we can call the <u>get()</u> API which returns right away if the operation already completed as we were executing other code, or else it blocks until the operation completes.</p>
<p>Our assertion indeed proves that the content from the file has been read.</p>
<p>If we had changed the position parameter in the <u>read</u> API call from zero to something else, we would see the effect too. For example, the seventh character in the string <u>baeldung.com</u> is <u>g</u>. So changing the position parameter to 7 would cause the buffer to contain the string <u>g.com</u>.</p>
<h3 id="toc_5"><strong>3.2. The <u>CompletionHandler</u> Approach</strong></h3>
<p>Next, we will see how to read a file’s contents using a <u>CompletionHandler</u> instance:</p>
<pre><code class="language-java">@Test
public void
givenPath_whenReadsContentWithCompletionHandler_thenCorrect() {
Path path = Paths.get(
URI.create( this.getClass().getResource("/file.txt").toString()));
AsynchronousFileChannel fileChannel
= AsynchronousFileChannel.open(path, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
fileChannel.read(
buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
// result is number of bytes read
// attachment is the buffer containing content
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
}
});
}
</code></pre>
<p>In the above code, we use the second variant of the <u>read</u> API. It still takes a <u>ByteBuffer</u> and the start position of the <u>read</u> operation as the first and second parameters respectively. The third parameter is the <u>CompletionHandler</u> instance.</p>
<p>The first generic type of the completion handler is the return type of the operation, in this case, an Integer representing the number of bytes read.</p>
<p>The second is the type of the attachment. We have chosen to attach the buffer such that when the <u>read</u> completes, we can use the content of the file inside the <u>completed</u> callback API.</p>
<p>Semantically speaking, this is not really a valid unit test since we cannot do an assertion inside the <u>completed</u> callback method. However, we do this for the sake of consistency and because we want our code to be as <u>copy-paste-run-</u>able as possible.</p>
<h2 id="toc_6"><strong>4. Writing to a File</strong></h2>
<p>Java NIO2 also allows us to perform write operations on a file. Just as we did with other operations, we can write to a file in two ways. Using <u>Future</u> and using <u>CompletionHandler</u>. In each case, we use the <u>write</u> API of the returned channel.</p>
<p>Creating an <u>AsynchronousFileChannel</u> for writing to a file can be done like this:</p>
<pre><code class="language-java">AsynchronousFileChannel fileChannel
= AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
</code></pre>
<h3 id="toc_7"><strong>4.1. Special Considerations</strong></h3>
<p>Notice the option passed to the <u>open</u> API. We can also add another option <u>StandardOpenOption.CREATE</u> if we want the file represented by a <u>path</u> to be created in case it does not already exist. Another common option is <u>StandardOpenOption.APPEND</u> which does not over-write existing content in the file.</p>
<p>We will use the following line for creating our file channel for test purposes:</p>
<pre><code class="language-java">AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
path, WRITE, CREATE, DELETE_ON_CLOSE);
</code></pre>
<p>This way, we will provide any arbitrary path and be sure that the file will be created. After the test exits, the created file will be deleted. To ensure the files created are not deleted after the test exits, you can remove the last option.</p>
<p>To run assertions, we will need to read the file content where possible after writing to them. Let’s hide the logic for reading in a separate method to avoid redundancy:</p>
<pre><code class="language-java">public static String readContent(Path file) {
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
file, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> operation = fileChannel.read(buffer, 0);
// run other code as operation continues in background
operation.get();
String fileContent = new String(buffer.array()).trim();
buffer.clear();
return fileContent;
}
</code></pre>
<h3 id="toc_8"><strong>4.2. The <u>Future</u> Approach</strong></h3>
<p>To write to a file asynchronously using the <u>Future</u> class:</p>
<pre><code class="language-java">@Test
public void
givenPathAndContent_whenWritesToFileWithFuture_thenCorrect() {
String fileName = UUID.randomUUID().toString();
Path path = Paths.get(fileName);
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
path, WRITE, CREATE, DELETE_ON_CLOSE);
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("hello world".getBytes());
buffer.flip();
Future<Integer> operation = fileChannel.write(buffer, 0);
buffer.clear();
//run other code as operation continues in background
operation.get();
String content = readContent(path);
assertEquals("hello world", content);
}
</code></pre>
<p>Let’s inspect what is happening in the above code. We create a random file name and use it to get a <u>Path</u> object. We use this path to open an asynchronous file channel with the previously mentioned options.</p>
<p>We then put the content we want to write to the file in a buffer and perform the <u>write</u>. We use our helper method to read the contents of the file and indeed confirm that it is what we expect.</p>
<h3 id="toc_9"><strong>4.3. The <u>CompletionHandler</u> Approach</strong></h3>
<p>We can also use the completion handler so that we don’t have to wait for the operation to complete in a while loop:</p>
<pre><code class="language-java">@Test
public void
givenPathAndContent_whenWritesToFileWithHandler_thenCorrect() {
String fileName = UUID.randomUUID().toString();
Path path = Paths.get(fileName);
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
path, WRITE, CREATE, DELETE_ON_CLOSE);
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("hello world".getBytes());
buffer.flip();
fileChannel.write(
buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
// result is number of bytes written
// attachment is the buffer
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
}
});
}
</code></pre>
<p>When we call the write API this time, the only new thing is a third parameter where we pass an anonymous inner class of type <u>CompletionHandler</u>.</p>
<p>When the operation completes, the class calls it’s completed method within which we can define what should happen.</p>
<h2 id="toc_10"><strong>5. Conclusion</strong></h2>
<p>In this article, we have explored some of the most important features of the Asynchronous File Channel APIs of Java NIO2.</p>
<p>To get all code snippets and the full source code for this article, you can visit the <a href="https://github.com/eugenp/tutorials/tree/master/core-java-io">Github project</a>.</p>
</div>
<div class="row">
<div class="large-6 columns">
<p class="text-left" style="padding:15px 0px;">
<a href="15263920307765.html"
title="Previous Post: “Exit Trap” 让你的 Bash 脚本更稳固可靠">« “Exit Trap” 让你的 Bash 脚本更稳固可靠</a>
</p>
</div>
<div class="large-6 columns">
<p class="text-right" style="padding:15px 0px;">
<a href="15262258657164.html"
title="Next Post: 飞哥教你使用异步编程提升服务性能">飞哥教你使用异步编程提升服务性能 »</a>
</p>
</div>
</div>
<div class="comments-wrap">
<div class="share-comments">
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5ae58078c0d7b2ab"></script>
</div>
</div>
</div><!-- article-wrap -->
</div><!-- large 8 -->
<div class="large-4 medium-4 columns">
<div class="hide-for-small">
<div id="sidebar" class="sidebar">
<div id="site-info" class="site-info">
<div class="site-a-logo"><img src="./asset/img/logo.jpg" /></div>
<h1>Junkman</h1>
<div class="site-des">“拾荒者”一词来自凯文・凯利的《失控》中关于机器学习的故事(“收集癖好机”如何完成他的收集工作)。</div>
<div class="social">
<a target="_blank" class="github" target="_blank" href="https://github.com/panlw/" title="GitHub">GitHub</a>
<a target="_blank" class="rss" href="atom.xml" title="RSS">RSS</a>
</div>
</div>
<div id="site-categories" class="side-item ">
<div class="side-header">
<h2>Categories</h2>
</div>
<div class="side-content">
<p class="cat-list">
<a href="Infra.html"><strong>Infra</strong></a>
<a href="Coding.html"><strong>Coding</strong></a>
<a href="Modeling.html"><strong>Modeling</strong></a>
<a href="Archtecting.html"><strong>Archtecting</strong></a>
</p>
</div>
</div>
<div id="site-categories" class="side-item">
<div class="side-header">
<h2>Recent Posts</h2>
</div>
<div class="side-content">
<ul class="posts-list">
<li class="post">
<a href="15517999043443.html">The Art of Crafting Architectural Diagrams</a>
</li>
<li class="post">
<a href="15517997955971.html">为什么说我们需要软件架构图?</a>
</li>
<li class="post">
<a href="15516128677869.html">DNS Servers That Offer Privacy and Filtering</a>
</li>
<li class="post">
<a href="15516123108194.html">Airbnb's Migration from Monolith to Services</a>
</li>
<li class="post">
<a href="15516097487470.html">Events As First-Class Citizens</a>
</li>
</ul>
</div>
</div>
</div><!-- sidebar -->
</div><!-- hide for small -->
</div><!-- large 4 -->
</div><!-- row -->
<div class="page-bottom clearfix">
<div class="row">
<p class="copyright">Copyright © 2015
Powered by <a target="_blank" href="http://www.mweb.im">MWeb</a>,
Theme used <a target="_blank" href="http://github.com">GitHub CSS</a>.</p>
</div>
</div>
</section>
</div>
</div>
<script src="asset/js/foundation.min.js"></script>
<script>
$(document).foundation();
function fixSidebarHeight(){
var w1 = $('.markdown-body').height();
var w2 = $('#sidebar').height();
if (w1 > w2) { $('#sidebar').height(w1); };
}
$(function(){
fixSidebarHeight();
})
$(window).load(function(){
fixSidebarHeight();
});
</script>
<script src="asset/chart/all-min.js"></script><script type="text/javascript">$(function(){ var mwebii=0; var mwebChartEleId = 'mweb-chart-ele-'; $('pre>code').each(function(){ mwebii++; var eleiid = mwebChartEleId+mwebii; if($(this).hasClass('language-sequence')){ var ele = $(this).addClass('nohighlight').parent(); $('<div id="'+eleiid+'"></div>').insertAfter(ele); ele.hide(); var diagram = Diagram.parse($(this).text()); diagram.drawSVG(eleiid,{theme: 'simple'}); }else if($(this).hasClass('language-flow')){ var ele = $(this).addClass('nohighlight').parent(); $('<div id="'+eleiid+'"></div>').insertAfter(ele); ele.hide(); var diagram = flowchart.parse($(this).text()); diagram.drawSVG(eleiid); } });});</script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><script type="text/x-mathjax-config">MathJax.Hub.Config({TeX: { equationNumbers: { autoNumber: "AMS" } }});</script>
</body>
</html>