OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 part of dart.io; | |
6 | |
7 /** | |
8 * The modes in which a File can be opened. | |
9 */ | |
10 class FileMode { | |
11 /// The mode for opening a file only for reading. | |
12 static const READ = const FileMode._internal(0); | |
13 /// Mode for opening a file for reading and writing. The file is | |
14 /// overwritten if it already exists. The file is created if it does not | |
15 /// already exist. | |
16 static const WRITE = const FileMode._internal(1); | |
17 /// Mode for opening a file for reading and writing to the | |
18 /// end of it. The file is created if it does not already exist. | |
19 static const APPEND = const FileMode._internal(2); | |
20 /// Mode for opening a file for writing *only*. The file is | |
21 /// overwritten if it already exists. The file is created if it does not | |
22 /// already exist. | |
23 static const WRITE_ONLY = const FileMode._internal(3); | |
24 /// Mode for opening a file for writing *only* to the | |
25 /// end of it. The file is created if it does not already exist. | |
26 static const WRITE_ONLY_APPEND = const FileMode._internal(4); | |
27 final int _mode; | |
28 | |
29 const FileMode._internal(this._mode); | |
30 } | |
31 | |
32 /// The mode for opening a file only for reading. | |
33 const READ = FileMode.READ; | |
34 /// The mode for opening a file for reading and writing. The file is | |
35 /// overwritten if it already exists. The file is created if it does not | |
36 /// already exist. | |
37 const WRITE = FileMode.WRITE; | |
38 /// The mode for opening a file for reading and writing to the | |
39 /// end of it. The file is created if it does not already exist. | |
40 const APPEND = FileMode.APPEND; | |
41 /// Mode for opening a file for writing *only*. The file is | |
42 /// overwritten if it already exists. The file is created if it does not | |
43 /// already exist. | |
44 const WRITE_ONLY = FileMode.WRITE_ONLY; | |
45 /// Mode for opening a file for writing *only* to the | |
46 /// end of it. The file is created if it does not already exist. | |
47 const WRITE_ONLY_APPEND = FileMode.WRITE_ONLY_APPEND; | |
48 | |
49 | |
50 /// Type of lock when requesting a lock on a file. | |
51 enum FileLock { | |
52 /// Shared file lock. | |
53 SHARED, | |
54 /// Exclusive file lock. | |
55 EXCLUSIVE | |
56 } | |
57 | |
58 /** | |
59 * A reference to a file on the file system. | |
60 * | |
61 * A File instance is an object that holds a [path] on which operations can | |
62 * be performed. | |
63 * You can get the parent directory of the file using the getter [parent], | |
64 * a property inherited from [FileSystemEntity]. | |
65 * | |
66 * Create a new File object with a pathname to access the specified file on the | |
67 * file system from your program. | |
68 * | |
69 * var myFile = new File('file.txt'); | |
70 * | |
71 * The File class contains methods for manipulating files and their contents. | |
72 * Using methods in this class, you can open and close files, read to and write | |
73 * from them, create and delete them, and check for their existence. | |
74 * | |
75 * When reading or writing a file, you can use streams (with [openRead]), | |
76 * random access operations (with [open]), | |
77 * or convenience methods such as [readAsString], | |
78 * | |
79 * Most methods in this class occur in synchronous and asynchronous pairs, | |
80 * for example, [readAsString] and [readAsStringSync]. | |
81 * Unless you have a specific reason for using the synchronous version | |
82 * of a method, prefer the asynchronous version to avoid blocking your program. | |
83 * | |
84 * ## If path is a link | |
85 * | |
86 * If [path] is a symbolic link, rather than a file, | |
87 * then the methods of File operate on the ultimate target of the | |
88 * link, except for [delete] and [deleteSync], which operate on | |
89 * the link. | |
90 * | |
91 * ## Read from a file | |
92 * | |
93 * The following code sample reads the entire contents from a file as a string | |
94 * using the asynchronous [readAsString] method: | |
95 * | |
96 * import 'dart:async'; | |
97 * import 'dart:io'; | |
98 * | |
99 * void main() { | |
100 * new File('file.txt').readAsString().then((String contents) { | |
101 * print(contents); | |
102 * }); | |
103 * } | |
104 * | |
105 * A more flexible and useful way to read a file is with a [Stream]. | |
106 * Open the file with [openRead], which returns a stream that | |
107 * provides the data in the file as chunks of bytes. | |
108 * Listen to the stream for data and process as needed. | |
109 * You can use various transformers in succession to manipulate the | |
110 * data into the required format or to prepare it for output. | |
111 * | |
112 * You might want to use a stream to read large files, | |
113 * to manipulate the data with tranformers, | |
114 * or for compatibility with another API, such as [WebSocket]s. | |
115 * | |
116 * import 'dart:io'; | |
117 * import 'dart:convert'; | |
118 * import 'dart:async'; | |
119 * | |
120 * main() { | |
121 * final file = new File('file.txt'); | |
122 * Stream<List<int>> inputStream = file.openRead(); | |
123 * | |
124 * inputStream | |
125 * .transform(UTF8.decoder) // Decode bytes to UTF8. | |
126 * .transform(new LineSplitter()) // Convert stream to individual lines. | |
127 * .listen((String line) { // Process results. | |
128 * print('$line: ${line.length} bytes'); | |
129 * }, | |
130 * onDone: () { print('File is now closed.'); }, | |
131 * onError: (e) { print(e.toString()); }); | |
132 * } | |
133 * | |
134 * ## Write to a file | |
135 * | |
136 * To write a string to a file, use the [writeAsString] method: | |
137 * | |
138 * import 'dart:io'; | |
139 * | |
140 * void main() { | |
141 * final filename = 'file.txt'; | |
142 * new File(filename).writeAsString('some content') | |
143 * .then((File file) { | |
144 * // Do something with the file. | |
145 * }); | |
146 * } | |
147 * | |
148 * You can also write to a file using a [Stream]. Open the file with | |
149 * [openWrite], which returns a stream to which you can write data. | |
150 * Be sure to close the file with the [close] method. | |
151 * | |
152 * import 'dart:io'; | |
153 * | |
154 * void main() { | |
155 * var file = new File('file.txt'); | |
156 * var sink = file.openWrite(); | |
157 * sink.write('FILE ACCESSED ${new DateTime.now()}\n'); | |
158 * | |
159 * // Close the IOSink to free system resources. | |
160 * sink.close(); | |
161 * } | |
162 * | |
163 * ## The use of Futures | |
164 * | |
165 * To avoid unintentional blocking of the program, | |
166 * several methods use a [Future] to return a value. For example, | |
167 * the [length] method, which gets the length of a file, returns a Future. | |
168 * Use `then` to register a callback function, which is called when | |
169 * the value is ready. | |
170 * | |
171 * import 'dart:io'; | |
172 * | |
173 * main() { | |
174 * final file = new File('file.txt'); | |
175 * | |
176 * file.length().then((len) { | |
177 * print(len); | |
178 * }); | |
179 * } | |
180 * | |
181 * In addition to length, the [exists], [lastModified], [stat], and | |
182 * other methods, return Futures. | |
183 * | |
184 * ## Other resources | |
185 * | |
186 * * [Dart by Example](https://www.dartlang.org/dart-by-example/#files-directori
es-and-symlinks) | |
187 * provides additional task-oriented code samples that show how to use | |
188 * various API from the Directory class and the related [File] class. | |
189 * | |
190 * * [I/O for Command-Line | |
191 * Apps](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartio---
io-for-command-line-apps) | |
192 * a section from _A Tour of the Dart Libraries_ covers files and directories. | |
193 * | |
194 * * [Write Command-Line Apps](https://www.dartlang.org/docs/tutorials/cmdline/)
, | |
195 * a tutorial about writing command-line apps, includes information about | |
196 * files and directories. | |
197 */ | |
198 abstract class File implements FileSystemEntity { | |
199 /** | |
200 * Creates a [File] object. | |
201 * | |
202 * If [path] is a relative path, it will be interpreted relative to the | |
203 * current working directory (see [Directory.current]), when used. | |
204 * | |
205 * If [path] is an absolute path, it will be immune to changes to the | |
206 * current working directory. | |
207 */ | |
208 factory File(String path) => new _File(path); | |
209 | |
210 /** | |
211 * Create a File object from a URI. | |
212 * | |
213 * If [uri] cannot reference a file this throws [UnsupportedError]. | |
214 */ | |
215 factory File.fromUri(Uri uri) => new File(uri.toFilePath()); | |
216 | |
217 /** | |
218 * Create the file. Returns a [:Future<File>:] that completes with | |
219 * the file when it has been created. | |
220 * | |
221 * If [recursive] is false, the default, the file is created only if | |
222 * all directories in the path exist. If [recursive] is true, all | |
223 * non-existing path components are created. | |
224 * | |
225 * Existing files are left untouched by [create]. Calling [create] on an | |
226 * existing file might fail if there are restrictive permissions on | |
227 * the file. | |
228 * | |
229 * Completes the future with a [FileSystemException] if the operation fails. | |
230 */ | |
231 Future<File> create({bool recursive: false}); | |
232 | |
233 /** | |
234 * Synchronously create the file. Existing files are left untouched | |
235 * by [createSync]. Calling [createSync] on an existing file might fail | |
236 * if there are restrictive permissions on the file. | |
237 * | |
238 * If [recursive] is false, the default, the file is created | |
239 * only if all directories in the path exist. | |
240 * If [recursive] is true, all non-existing path components are created. | |
241 * | |
242 * Throws a [FileSystemException] if the operation fails. | |
243 */ | |
244 void createSync({bool recursive: false}); | |
245 | |
246 /** | |
247 * Renames this file. Returns a `Future<File>` that completes | |
248 * with a [File] instance for the renamed file. | |
249 * | |
250 * If [newPath] identifies an existing file, that file is | |
251 * replaced. If [newPath] identifies an existing directory, the | |
252 * operation fails and the future completes with an exception. | |
253 */ | |
254 Future<File> rename(String newPath); | |
255 | |
256 /** | |
257 * Synchronously renames this file. Returns a [File] | |
258 * instance for the renamed file. | |
259 * | |
260 * If [newPath] identifies an existing file, that file is | |
261 * replaced. If [newPath] identifies an existing directory the | |
262 * operation fails and an exception is thrown. | |
263 */ | |
264 File renameSync(String newPath); | |
265 | |
266 /** | |
267 * Copy this file. Returns a `Future<File>` that completes | |
268 * with a [File] instance for the copied file. | |
269 * | |
270 * If [newPath] identifies an existing file, that file is | |
271 * replaced. If [newPath] identifies an existing directory, the | |
272 * operation fails and the future completes with an exception. | |
273 */ | |
274 Future<File> copy(String newPath); | |
275 | |
276 /** | |
277 * Synchronously copy this file. Returns a [File] | |
278 * instance for the copied file. | |
279 * | |
280 * If [newPath] identifies an existing file, that file is | |
281 * replaced. If [newPath] identifies an existing directory the | |
282 * operation fails and an exception is thrown. | |
283 */ | |
284 File copySync(String newPath); | |
285 | |
286 /** | |
287 * Get the length of the file. Returns a [:Future<int>:] that | |
288 * completes with the length in bytes. | |
289 */ | |
290 Future<int> length(); | |
291 | |
292 /** | |
293 * Synchronously get the length of the file. | |
294 * | |
295 * Throws a [FileSystemException] if the operation fails. | |
296 */ | |
297 int lengthSync(); | |
298 | |
299 /** | |
300 * Returns a [File] instance whose path is the absolute path to [this]. | |
301 * | |
302 * The absolute path is computed by prefixing | |
303 * a relative path with the current working directory, and returning | |
304 * an absolute path unchanged. | |
305 */ | |
306 File get absolute; | |
307 | |
308 /** | |
309 * Get the last-modified time of the file. Returns a | |
310 * [:Future<DateTime>:] that completes with a [DateTime] object for the | |
311 * modification date. | |
312 */ | |
313 Future<DateTime> lastModified(); | |
314 | |
315 /** | |
316 * Get the last-modified time of the file. Throws an exception | |
317 * if the file does not exist. | |
318 * | |
319 * Throws a [FileSystemException] if the operation fails. | |
320 */ | |
321 DateTime lastModifiedSync(); | |
322 | |
323 /** | |
324 * Open the file for random access operations. Returns a | |
325 * [:Future<RandomAccessFile>:] that completes with the opened | |
326 * random access file. [RandomAccessFile]s must be closed using the | |
327 * [RandomAccessFile.close] method. | |
328 * | |
329 * Files can be opened in three modes: | |
330 * | |
331 * [FileMode.READ]: open the file for reading. | |
332 * | |
333 * [FileMode.WRITE]: open the file for both reading and writing and | |
334 * truncate the file to length zero. If the file does not exist the | |
335 * file is created. | |
336 * | |
337 * [FileMode.APPEND]: same as [FileMode.WRITE] except that the file is | |
338 * not truncated. | |
339 */ | |
340 Future<RandomAccessFile> open({FileMode mode: FileMode.READ}); | |
341 | |
342 /** | |
343 * Synchronously open the file for random access operations. The | |
344 * result is a [RandomAccessFile] on which random access operations | |
345 * can be performed. Opened [RandomAccessFile]s must be closed using | |
346 * the [RandomAccessFile.close] method. | |
347 * | |
348 * See [open] for information on the [mode] argument. | |
349 * | |
350 * Throws a [FileSystemException] if the operation fails. | |
351 */ | |
352 RandomAccessFile openSync({FileMode mode: FileMode.READ}); | |
353 | |
354 /** | |
355 * Create a new independent [Stream] for the contents of this file. | |
356 * | |
357 * If [start] is present, the file will be read from byte-offset [start]. | |
358 * Otherwise from the beginning (index 0). | |
359 * | |
360 * If [end] is present, only up to byte-index [end] will be read. Otherwise, | |
361 * until end of file. | |
362 * | |
363 * In order to make sure that system resources are freed, the stream | |
364 * must be read to completion or the subscription on the stream must | |
365 * be cancelled. | |
366 */ | |
367 Stream<List<int>> openRead([int start, int end]); | |
368 | |
369 /** | |
370 * Creates a new independent [IOSink] for the file. The | |
371 * [IOSink] must be closed when no longer used, to free | |
372 * system resources. | |
373 * | |
374 * An [IOSink] for a file can be opened in two modes: | |
375 * | |
376 * * [FileMode.WRITE]: truncates the file to length zero. | |
377 * * [FileMode.APPEND]: sets the initial write position to the end | |
378 * of the file. | |
379 * | |
380 * When writing strings through the returned [IOSink] the encoding | |
381 * specified using [encoding] will be used. The returned [IOSink] | |
382 * has an [:encoding:] property which can be changed after the | |
383 * [IOSink] has been created. | |
384 */ | |
385 IOSink openWrite({FileMode mode: FileMode.WRITE, | |
386 Encoding encoding: UTF8}); | |
387 | |
388 /** | |
389 * Read the entire file contents as a list of bytes. Returns a | |
390 * [:Future<List<int>>:] that completes with the list of bytes that | |
391 * is the contents of the file. | |
392 */ | |
393 Future<List<int>> readAsBytes(); | |
394 | |
395 /** | |
396 * Synchronously read the entire file contents as a list of bytes. | |
397 * | |
398 * Throws a [FileSystemException] if the operation fails. | |
399 */ | |
400 List<int> readAsBytesSync(); | |
401 | |
402 /** | |
403 * Read the entire file contents as a string using the given | |
404 * [Encoding]. | |
405 * | |
406 * Returns a [:Future<String>:] that completes with the string once | |
407 * the file contents has been read. | |
408 */ | |
409 Future<String> readAsString({Encoding encoding: UTF8}); | |
410 | |
411 /** | |
412 * Synchronously read the entire file contents as a string using the | |
413 * given [Encoding]. | |
414 * | |
415 * Throws a [FileSystemException] if the operation fails. | |
416 */ | |
417 String readAsStringSync({Encoding encoding: UTF8}); | |
418 | |
419 /** | |
420 * Read the entire file contents as lines of text using the given | |
421 * [Encoding]. | |
422 * | |
423 * Returns a [:Future<List<String>>:] that completes with the lines | |
424 * once the file contents has been read. | |
425 */ | |
426 Future<List<String>> readAsLines({Encoding encoding: UTF8}); | |
427 | |
428 /** | |
429 * Synchronously read the entire file contents as lines of text | |
430 * using the given [Encoding]. | |
431 * | |
432 * Throws a [FileSystemException] if the operation fails. | |
433 */ | |
434 List<String> readAsLinesSync({Encoding encoding: UTF8}); | |
435 | |
436 /** | |
437 * Write a list of bytes to a file. | |
438 * | |
439 * Opens the file, writes the list of bytes to it, and closes the file. | |
440 * Returns a [:Future<File>:] that completes with this [File] object once | |
441 * the entire operation has completed. | |
442 * | |
443 * By default [writeAsBytes] creates the file for writing and truncates the | |
444 * file if it already exists. In order to append the bytes to an existing | |
445 * file, pass [FileMode.APPEND] as the optional mode parameter. | |
446 * | |
447 * If the argument [flush] is set to `true`, the data written will be | |
448 * flushed to the file system before the returned future completes. | |
449 */ | |
450 Future<File> writeAsBytes(List<int> bytes, | |
451 {FileMode mode: FileMode.WRITE, | |
452 bool flush: false}); | |
453 | |
454 /** | |
455 * Synchronously write a list of bytes to a file. | |
456 * | |
457 * Opens the file, writes the list of bytes to it and closes the file. | |
458 * | |
459 * By default [writeAsBytesSync] creates the file for writing and truncates | |
460 * the file if it already exists. In order to append the bytes to an existing | |
461 * file, pass [FileMode.APPEND] as the optional mode parameter. | |
462 * | |
463 * If the [flush] argument is set to `true` data written will be | |
464 * flushed to the file system before returning. | |
465 * | |
466 * Throws a [FileSystemException] if the operation fails. | |
467 */ | |
468 void writeAsBytesSync(List<int> bytes, | |
469 {FileMode mode: FileMode.WRITE, | |
470 bool flush: false}); | |
471 | |
472 /** | |
473 * Write a string to a file. | |
474 * | |
475 * Opens the file, writes the string in the given encoding, and closes the | |
476 * file. Returns a [:Future<File>:] that completes with this [File] object | |
477 * once the entire operation has completed. | |
478 * | |
479 * By default [writeAsString] creates the file for writing and truncates the | |
480 * file if it already exists. In order to append the bytes to an existing | |
481 * file, pass [FileMode.APPEND] as the optional mode parameter. | |
482 * | |
483 * If the argument [flush] is set to `true`, the data written will be | |
484 * flushed to the file system before the returned future completes. | |
485 * | |
486 */ | |
487 Future<File> writeAsString(String contents, | |
488 {FileMode mode: FileMode.WRITE, | |
489 Encoding encoding: UTF8, | |
490 bool flush: false}); | |
491 | |
492 /** | |
493 * Synchronously write a string to a file. | |
494 * | |
495 * Opens the file, writes the string in the given encoding, and closes the | |
496 * file. | |
497 * | |
498 * By default [writeAsStringSync] creates the file for writing and | |
499 * truncates the file if it already exists. In order to append the bytes | |
500 * to an existing file, pass [FileMode.APPEND] as the optional mode | |
501 * parameter. | |
502 * | |
503 * If the [flush] argument is set to `true` data written will be | |
504 * flushed to the file system before returning. | |
505 * | |
506 * Throws a [FileSystemException] if the operation fails. | |
507 */ | |
508 void writeAsStringSync(String contents, | |
509 {FileMode mode: FileMode.WRITE, | |
510 Encoding encoding: UTF8, | |
511 bool flush: false}); | |
512 | |
513 /** | |
514 * Get the path of the file. | |
515 */ | |
516 String get path; | |
517 } | |
518 | |
519 | |
520 /** | |
521 * `RandomAccessFile` provides random access to the data in a | |
522 * file. | |
523 * | |
524 * `RandomAccessFile` objects are obtained by calling the | |
525 * [:open:] method on a [File] object. | |
526 * | |
527 * A `RandomAccessFile` have both asynchronous and synchronous | |
528 * methods. The asynchronous methods all return a `Future` | |
529 * whereas the synchronous methods will return the result directly, | |
530 * and block the current isolate until the result is ready. | |
531 * | |
532 * At most one asynchronous method can be pending on a given `RandomAccessFile` | |
533 * instance at the time. If an asynchronous method is called when one is | |
534 * already in progress a [FileSystemException] is thrown. | |
535 * | |
536 * If an asynchronous method is pending it is also not possible to call any | |
537 * synchronous methods. This will also throw a [FileSystemException]. | |
538 */ | |
539 abstract class RandomAccessFile { | |
540 /** | |
541 * Closes the file. Returns a [:Future<RandomAccessFile>:] that | |
542 * completes with this RandomAccessFile when it has been closed. | |
543 */ | |
544 Future<RandomAccessFile> close(); | |
545 | |
546 /** | |
547 * Synchronously closes the file. | |
548 * | |
549 * Throws a [FileSystemException] if the operation fails. | |
550 */ | |
551 void closeSync(); | |
552 | |
553 /** | |
554 * Reads a byte from the file. Returns a [:Future<int>:] that | |
555 * completes with the byte, or with -1 if end-of-file has been reached. | |
556 */ | |
557 Future<int> readByte(); | |
558 | |
559 /** | |
560 * Synchronously reads a single byte from the file. If end-of-file | |
561 * has been reached -1 is returned. | |
562 * | |
563 * Throws a [FileSystemException] if the operation fails. | |
564 */ | |
565 int readByteSync(); | |
566 | |
567 /** | |
568 * Reads [bytes] bytes from a file and returns the result as a list of bytes. | |
569 */ | |
570 Future<List<int>> read(int bytes); | |
571 | |
572 /** | |
573 * Synchronously reads a maximum of [bytes] bytes from a file and | |
574 * returns the result in a list of bytes. | |
575 * | |
576 * Throws a [FileSystemException] if the operation fails. | |
577 */ | |
578 List<int> readSync(int bytes); | |
579 | |
580 /** | |
581 * Reads into an existing List<int> from the file. If [start] is present, the | |
582 * bytes will be filled into [buffer] from at index [start], otherwise index | |
583 * 0. If [end] is present, the [end] - [start] bytes will be read into | |
584 * [buffer], otherwise up to [buffer.length]. If [end] == [start] nothing | |
585 * happens. | |
586 * | |
587 * Returns a [:Future<int>:] that completes with the number of bytes read. | |
588 */ | |
589 Future<int> readInto(List<int> buffer, [int start = 0, int end]); | |
590 | |
591 /** | |
592 * Synchronously reads into an existing List<int> from the file. If [start] is | |
593 * present, the bytes will be filled into [buffer] from at index [start], | |
594 * otherwise index 0. If [end] is present, the [end] - [start] bytes will be | |
595 * read into [buffer], otherwise up to [buffer.length]. If [end] == [start] | |
596 * nothing happens. | |
597 * | |
598 * Throws a [FileSystemException] if the operation fails. | |
599 */ | |
600 int readIntoSync(List<int> buffer, [int start = 0, int end]); | |
601 | |
602 /** | |
603 * Writes a single byte to the file. Returns a | |
604 * [:Future<RandomAccessFile>:] that completes with this | |
605 * RandomAccessFile when the write completes. | |
606 */ | |
607 Future<RandomAccessFile> writeByte(int value); | |
608 | |
609 /** | |
610 * Synchronously writes a single byte to the file. Returns the | |
611 * number of bytes successfully written. | |
612 * | |
613 * Throws a [FileSystemException] if the operation fails. | |
614 */ | |
615 int writeByteSync(int value); | |
616 | |
617 /** | |
618 * Writes from a [List<int>] to the file. It will read the buffer from index | |
619 * [start] to index [end]. If [start] is omitted, it'll start from index 0. | |
620 * If [end] is omitted, it will write to end of [buffer]. | |
621 * | |
622 * Returns a [:Future<RandomAccessFile>:] that completes with this | |
623 * [RandomAccessFile] when the write completes. | |
624 */ | |
625 Future<RandomAccessFile> writeFrom( | |
626 List<int> buffer, [int start = 0, int end]); | |
627 | |
628 /** | |
629 * Synchronously writes from a [List<int>] to the file. It will read the | |
630 * buffer from index [start] to index [end]. If [start] is omitted, it'll | |
631 * start from index 0. If [end] is omitted, it will write to the end of | |
632 * [buffer]. | |
633 * | |
634 * Throws a [FileSystemException] if the operation fails. | |
635 */ | |
636 void writeFromSync(List<int> buffer, [int start = 0, int end]); | |
637 | |
638 /** | |
639 * Writes a string to the file using the given [Encoding]. Returns a | |
640 * [:Future<RandomAccessFile>:] that completes with this | |
641 * RandomAccessFile when the write completes. | |
642 */ | |
643 Future<RandomAccessFile> writeString(String string, | |
644 {Encoding encoding: UTF8}); | |
645 | |
646 /** | |
647 * Synchronously writes a single string to the file using the given | |
648 * [Encoding]. | |
649 * | |
650 * Throws a [FileSystemException] if the operation fails. | |
651 */ | |
652 void writeStringSync(String string, | |
653 {Encoding encoding: UTF8}); | |
654 | |
655 /** | |
656 * Gets the current byte position in the file. Returns a | |
657 * [:Future<int>:] that completes with the position. | |
658 */ | |
659 Future<int> position(); | |
660 | |
661 /** | |
662 * Synchronously gets the current byte position in the file. | |
663 * | |
664 * Throws a [FileSystemException] if the operation fails. | |
665 */ | |
666 int positionSync(); | |
667 | |
668 /** | |
669 * Sets the byte position in the file. Returns a | |
670 * [:Future<RandomAccessFile>:] that completes with this | |
671 * RandomAccessFile when the position has been set. | |
672 */ | |
673 Future<RandomAccessFile> setPosition(int position); | |
674 | |
675 /** | |
676 * Synchronously sets the byte position in the file. | |
677 * | |
678 * Throws a [FileSystemException] if the operation fails. | |
679 */ | |
680 void setPositionSync(int position); | |
681 | |
682 /** | |
683 * Truncates (or extends) the file to [length] bytes. Returns a | |
684 * [:Future<RandomAccessFile>:] that completes with this | |
685 * RandomAccessFile when the truncation has been performed. | |
686 */ | |
687 Future<RandomAccessFile> truncate(int length); | |
688 | |
689 /** | |
690 * Synchronously truncates (or extends) the file to [length] bytes. | |
691 * | |
692 * Throws a [FileSystemException] if the operation fails. | |
693 */ | |
694 void truncateSync(int length); | |
695 | |
696 /** | |
697 * Gets the length of the file. Returns a [:Future<int>:] that | |
698 * completes with the length in bytes. | |
699 */ | |
700 Future<int> length(); | |
701 | |
702 /** | |
703 * Synchronously gets the length of the file. | |
704 * | |
705 * Throws a [FileSystemException] if the operation fails. | |
706 */ | |
707 int lengthSync(); | |
708 | |
709 /** | |
710 * Flushes the contents of the file to disk. Returns a | |
711 * [:Future<RandomAccessFile>:] that completes with this | |
712 * RandomAccessFile when the flush operation completes. | |
713 */ | |
714 Future<RandomAccessFile> flush(); | |
715 | |
716 /** | |
717 * Synchronously flushes the contents of the file to disk. | |
718 * | |
719 * Throws a [FileSystemException] if the operation fails. | |
720 */ | |
721 void flushSync(); | |
722 | |
723 /** | |
724 * Locks the file or part of the file. | |
725 * | |
726 * By default an exclusive lock will be obtained, but that can be overridden | |
727 * by the [mode] argument. | |
728 * | |
729 * Locks the byte range from [start] to [end] of the file, with the | |
730 * byte at position `end` not included. If no arguments are | |
731 * specified, the full file is locked, If only `start` is specified | |
732 * the file is locked from byte position `start` to the end of the | |
733 * file, no matter how large it grows. It is possible to specify an | |
734 * explicit value of `end` which is past the current length of the file. | |
735 * | |
736 * To obtain an exclusive lock on a file it must be opened for writing. | |
737 * | |
738 * *NOTE* file locking does have slight differences in behavior across | |
739 * platforms: | |
740 * | |
741 * On Linux and OS X this uses advisory locks, which have the | |
742 * surprising semantics that all locks associated with a given file | |
743 * are removed when *any* file descriptor for that file is closed by | |
744 * the process. Note that this does not actually lock the file for | |
745 * access. Also note that advisory locks are on a process | |
746 * level. This means that several isolates in the same process can | |
747 * obtain an exclusive lock on the same file. | |
748 * | |
749 * On Windows the regions used for lock and unlock needs to match. If that | |
750 * is not the case unlocking will result in the OS error "The segment is | |
751 * already unlocked". | |
752 */ | |
753 Future<RandomAccessFile> lock( | |
754 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]); | |
755 | |
756 /** | |
757 * Synchronously locks the file or part of the file. | |
758 * | |
759 * By default an exclusive lock will be obtained, but that can be overridden | |
760 * by the [mode] argument. | |
761 * | |
762 * Locks the byte range from [start] to [end] of the file ,with the | |
763 * byte at position `end` not included. If no arguments are | |
764 * specified, the full file is locked, If only `start` is specified | |
765 * the file is locked from byte position `start` to the end of the | |
766 * file, no matter how large it grows. It is possible to specify an | |
767 * explicit value of `end` which is past the current length of the file. | |
768 * | |
769 * To obtain an exclusive lock on a file it must be opened for writing. | |
770 * | |
771 * *NOTE* file locking does have slight differences in behavior across | |
772 * platforms: | |
773 * | |
774 * On Linux and OS X this uses advisory locks, which have the | |
775 * surprising semantics that all locks associated with a given file | |
776 * are removed when *any* file descriptor for that file is closed by | |
777 * the process. Note that this does not actually lock the file for | |
778 * access. Also note that advisory locks are on a process | |
779 * level. This means that several isolates in the same process can | |
780 * obtain an exclusive lock on the same file. | |
781 * | |
782 * On Windows the regions used for lock and unlock needs to match. If that | |
783 * is not the case unlocking will result in the OS error "The segment is | |
784 * already unlocked". | |
785 * | |
786 */ | |
787 void lockSync( | |
788 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]); | |
789 | |
790 /** | |
791 * Unlocks the file or part of the file. | |
792 * | |
793 * Unlocks the byte range from [start] to [end] of the file, with | |
794 * the byte at position `end` not included. If no arguments are | |
795 * specified, the full file is unlocked, If only `start` is | |
796 * specified the file is unlocked from byte position `start` to the | |
797 * end of the file. | |
798 * | |
799 * *NOTE* file locking does have slight differences in behavior across | |
800 * platforms: | |
801 * | |
802 * See [lock] for more details. | |
803 */ | |
804 Future<RandomAccessFile> unlock([int start = 0, int end = -1]); | |
805 | |
806 /** | |
807 * Synchronously unlocks the file or part of the file. | |
808 * | |
809 * Unlocks the byte range from [start] to [end] of the file, with | |
810 * the byte at position `end` not included. If no arguments are | |
811 * specified, the full file is unlocked, If only `start` is | |
812 * specified the file is unlocked from byte position `start` to the | |
813 * end of the file. | |
814 * | |
815 * *NOTE* file locking does have slight differences in behavior across | |
816 * platforms: | |
817 * | |
818 * See [lockSync] for more details. | |
819 */ | |
820 void unlockSync([int start = 0, int end = -1]); | |
821 | |
822 /** | |
823 * Returns a human-readable string for this RandomAccessFile instance. | |
824 */ | |
825 String toString(); | |
826 | |
827 /** | |
828 * Gets the path of the file underlying this RandomAccessFile. | |
829 */ | |
830 String get path; | |
831 } | |
832 | |
833 | |
834 /** | |
835 * Exception thrown when a file operation fails. | |
836 */ | |
837 class FileSystemException implements IOException { | |
838 /** | |
839 * Message describing the error. This does not include any detailed | |
840 * information form the underlying OS error. Check [osError] for | |
841 * that information. | |
842 */ | |
843 final String message; | |
844 | |
845 /** | |
846 * The file system path on which the error occurred. Can be `null` | |
847 * if the exception does not relate directly to a file system path. | |
848 */ | |
849 final String path; | |
850 | |
851 /** | |
852 * The underlying OS error. Can be `null` if the exception is not | |
853 * raised due to an OS error. | |
854 */ | |
855 final OSError osError; | |
856 | |
857 /** | |
858 * Creates a new FileSystemException with an optional error message | |
859 * [message], optional file system path [path] and optional OS error | |
860 * [osError]. | |
861 */ | |
862 const FileSystemException([this.message = "", this.path = "", this.osError]); | |
863 | |
864 String toString() { | |
865 StringBuffer sb = new StringBuffer(); | |
866 sb.write("FileSystemException"); | |
867 if (!message.isEmpty) { | |
868 sb.write(": $message"); | |
869 if (path != null) { | |
870 sb.write(", path = '$path'"); | |
871 } | |
872 if (osError != null) { | |
873 sb.write(" ($osError)"); | |
874 } | |
875 } else if (osError != null) { | |
876 sb.write(": $osError"); | |
877 if (path != null) { | |
878 sb.write(", path = '$path'"); | |
879 } | |
880 } else if (path != null) { | |
881 sb.write(": $path"); | |
882 } | |
883 return sb.toString(); | |
884 } | |
885 } | |
OLD | NEW |