0
# File System Operations
1
2
Okio's FileSystem provides cross-platform file system access with path manipulation, metadata queries, and efficient file I/O operations. It abstracts platform differences while providing comprehensive file management capabilities.
3
4
## Capabilities
5
6
### FileSystem Interface
7
8
Core file system operations for cross-platform file access.
9
10
```kotlin { .api }
11
/**
12
* Read/write access to a hierarchical file collection
13
* Provides cross-platform file system operations
14
*/
15
abstract class FileSystem : Closeable {
16
/**
17
* Resolves path to canonical form, following symlinks
18
* @param path Path to canonicalize
19
* @return Canonical path
20
* @throws IOException if path resolution fails
21
*/
22
@Throws(IOException::class)
23
abstract fun canonicalize(path: Path): Path
24
25
/**
26
* Gets metadata for the file or directory at path
27
* @param path Path to get metadata for
28
* @return FileMetadata describing the file
29
* @throws FileNotFoundException if path doesn't exist
30
* @throws IOException if an I/O error occurs
31
*/
32
@Throws(IOException::class)
33
abstract fun metadata(path: Path): FileMetadata
34
35
/**
36
* Gets metadata for the file or directory at path, or null if not found
37
* @param path Path to get metadata for
38
* @return FileMetadata describing the file, or null if not found
39
* @throws IOException if an I/O error occurs
40
*/
41
@Throws(IOException::class)
42
abstract fun metadataOrNull(path: Path): FileMetadata?
43
44
/**
45
* Checks if a file or directory exists at path
46
* @param path Path to check
47
* @return true if path exists
48
*/
49
fun exists(path: Path): Boolean
50
51
/**
52
* Lists the contents of a directory
53
* @param dir Directory path to list
54
* @return List of paths in the directory
55
* @throws FileNotFoundException if directory doesn't exist
56
* @throws IOException if an I/O error occurs
57
*/
58
@Throws(IOException::class)
59
abstract fun list(dir: Path): List<Path>
60
61
/**
62
* Lists the contents of a directory, or null if not found
63
* @param dir Directory path to list
64
* @return List of paths in the directory, or null if not found
65
* @throws IOException if an I/O error occurs
66
*/
67
@Throws(IOException::class)
68
abstract fun listOrNull(dir: Path): List<Path>?
69
70
/**
71
* Recursively lists all files and directories
72
* @param dir Directory to start listing from
73
* @param followSymlinks Whether to follow symbolic links
74
* @return Sequence of all nested paths
75
* @throws IOException if an I/O error occurs
76
*/
77
@Throws(IOException::class)
78
fun listRecursively(dir: Path, followSymlinks: Boolean = false): Sequence<Path>
79
80
/**
81
* Opens a file for reading
82
* @param file Path to file to open
83
* @return Source for reading the file
84
* @throws FileNotFoundException if file doesn't exist
85
* @throws IOException if an I/O error occurs
86
*/
87
@Throws(IOException::class)
88
abstract fun source(file: Path): Source
89
90
/**
91
* Opens a file for writing
92
* @param file Path to file to open
93
* @param mustCreate If true, fails if file already exists
94
* @return Sink for writing to the file
95
* @throws IOException if an I/O error occurs
96
*/
97
@Throws(IOException::class)
98
abstract fun sink(file: Path, mustCreate: Boolean = false): Sink
99
100
/**
101
* Opens a file for appending
102
* @param file Path to file to open
103
* @param mustExist If true, fails if file doesn't exist
104
* @return Sink for appending to the file
105
* @throws IOException if an I/O error occurs
106
*/
107
@Throws(IOException::class)
108
abstract fun appendingSink(file: Path, mustExist: Boolean = true): Sink
109
110
/**
111
* Opens a file for random access reading
112
* @param file Path to file to open
113
* @return FileHandle for random access
114
* @throws FileNotFoundException if file doesn't exist
115
* @throws IOException if an I/O error occurs
116
*/
117
@Throws(IOException::class)
118
abstract fun openReadOnly(file: Path): FileHandle
119
120
/**
121
* Opens a file for random access reading and writing
122
* @param file Path to file to open
123
* @param mustCreate If true, fails if file already exists
124
* @param mustExist If true, fails if file doesn't exist
125
* @return FileHandle for random access
126
* @throws IOException if an I/O error occurs
127
*/
128
@Throws(IOException::class)
129
abstract fun openReadWrite(
130
file: Path,
131
mustCreate: Boolean = false,
132
mustExist: Boolean = false
133
): FileHandle
134
135
/**
136
* Creates a directory
137
* @param dir Directory path to create
138
* @param mustCreate If true, fails if directory already exists
139
* @throws IOException if creation fails
140
*/
141
@Throws(IOException::class)
142
abstract fun createDirectory(dir: Path, mustCreate: Boolean = false)
143
144
/**
145
* Creates a directory and all necessary parent directories
146
* @param dir Directory path to create
147
* @param mustCreate If true, fails if directory already exists
148
* @throws IOException if creation fails
149
*/
150
@Throws(IOException::class)
151
fun createDirectories(dir: Path, mustCreate: Boolean = false)
152
153
/**
154
* Atomically moves a file or directory
155
* @param source Source path
156
* @param target Target path
157
* @throws IOException if move fails
158
*/
159
@Throws(IOException::class)
160
abstract fun atomicMove(source: Path, target: Path)
161
162
/**
163
* Copies a file
164
* @param source Source file path
165
* @param target Target file path
166
* @throws IOException if copy fails
167
*/
168
@Throws(IOException::class)
169
fun copy(source: Path, target: Path)
170
171
/**
172
* Deletes a file or empty directory
173
* @param path Path to delete
174
* @param mustExist If true, fails if path doesn't exist
175
* @throws IOException if deletion fails
176
*/
177
@Throws(IOException::class)
178
abstract fun delete(path: Path, mustExist: Boolean = true)
179
180
/**
181
* Recursively deletes a file or directory
182
* @param fileOrDirectory Path to delete
183
* @param mustExist If true, fails if path doesn't exist
184
* @throws IOException if deletion fails
185
*/
186
@Throws(IOException::class)
187
fun deleteRecursively(fileOrDirectory: Path, mustExist: Boolean = true)
188
189
/**
190
* Creates a symbolic link
191
* @param source Link path to create
192
* @param target Target path the link points to
193
* @throws IOException if link creation fails
194
*/
195
@Throws(IOException::class)
196
abstract fun createSymlink(source: Path, target: Path)
197
198
/**
199
* Closes the file system and releases resources
200
* @throws IOException if an error occurs during closing
201
*/
202
@Throws(IOException::class)
203
override fun close()
204
205
companion object {
206
/**
207
* The system's default file system
208
*/
209
val SYSTEM: FileSystem
210
211
/**
212
* Path to the system's temporary directory
213
*/
214
val SYSTEM_TEMPORARY_DIRECTORY: Path
215
}
216
}
217
```
218
219
### Inline File Operations
220
221
Convenient methods for simple file read/write operations.
222
223
```kotlin { .api }
224
/**
225
* Reads a file and executes the given block with a BufferedSource
226
* @param file Path to file to read
227
* @param readerAction Block to execute with BufferedSource
228
* @return Result of the reader action
229
* @throws IOException if an I/O error occurs
230
*/
231
@Throws(IOException::class)
232
inline fun <T> FileSystem.read(file: Path, readerAction: BufferedSource.() -> T): T
233
234
/**
235
* Writes to a file and executes the given block with a BufferedSink
236
* @param file Path to file to write
237
* @param mustCreate If true, fails if file already exists
238
* @param writerAction Block to execute with BufferedSink
239
* @return Result of the writer action
240
* @throws IOException if an I/O error occurs
241
*/
242
@Throws(IOException::class)
243
inline fun <T> FileSystem.write(
244
file: Path,
245
mustCreate: Boolean = false,
246
writerAction: BufferedSink.() -> T
247
): T
248
```
249
250
**Usage Examples:**
251
252
```kotlin
253
val fs = FileSystem.SYSTEM
254
val path = "/tmp/example.txt".toPath()
255
256
// Simple file operations
257
fs.write(path) {
258
writeUtf8("Hello, World!")
259
}
260
261
val content = fs.read(path) {
262
readUtf8()
263
}
264
println(content) // "Hello, World!"
265
266
// Directory operations
267
val dir = "/tmp/example_dir".toPath()
268
fs.createDirectory(dir)
269
fs.list(dir).forEach { println(it) }
270
271
// File metadata
272
val metadata = fs.metadata(path)
273
println("Size: ${metadata.size}")
274
println("Is file: ${metadata.isRegularFile}")
275
```
276
277
### Path Operations
278
279
Cross-platform path manipulation and navigation.
280
281
```kotlin { .api }
282
/**
283
* Hierarchical address on a filesystem
284
* Provides cross-platform path manipulation
285
*/
286
class Path private constructor() : Comparable<Path> {
287
/**
288
* Root path if this is absolute, null if relative
289
*/
290
val root: Path?
291
292
/**
293
* List of path segments (directory and file names)
294
*/
295
val segments: List<String>
296
297
/**
298
* Path segments as ByteString instances
299
*/
300
val segmentsBytes: List<ByteString>
301
302
/**
303
* True if this is an absolute path
304
*/
305
val isAbsolute: Boolean
306
307
/**
308
* True if this is a relative path
309
*/
310
val isRelative: Boolean
311
312
/**
313
* Windows drive letter, or null on other platforms
314
*/
315
val volumeLetter: Char?
316
317
/**
318
* Name of the final segment (file or directory name)
319
*/
320
val name: String
321
322
/**
323
* Name of the final segment as ByteString
324
*/
325
val nameBytes: ByteString
326
327
/**
328
* Parent directory path, or null if this is a root
329
*/
330
val parent: Path?
331
332
/**
333
* True if this path represents a root directory
334
*/
335
val isRoot: Boolean
336
337
/**
338
* Resolves a relative path against this path
339
* @param child Relative path or filename to resolve
340
* @return New path with child appended
341
*/
342
operator fun div(child: String): Path
343
344
/**
345
* Resolves a relative path against this path
346
* @param child ByteString path to resolve
347
* @return New path with child appended
348
*/
349
operator fun div(child: ByteString): Path
350
351
/**
352
* Resolves a path against this path
353
* @param child Path to resolve
354
* @return Resolved path
355
*/
356
operator fun div(child: Path): Path
357
358
/**
359
* Resolves a path with optional normalization
360
* @param child Child path to resolve
361
* @param normalize Whether to normalize the result
362
* @return Resolved path
363
*/
364
fun resolve(child: String, normalize: Boolean = false): Path
365
366
/**
367
* Resolves a ByteString path with optional normalization
368
* @param child Child path to resolve
369
* @param normalize Whether to normalize the result
370
* @return Resolved path
371
*/
372
fun resolve(child: ByteString, normalize: Boolean = false): Path
373
374
/**
375
* Resolves a path with optional normalization
376
* @param child Child path to resolve
377
* @param normalize Whether to normalize the result
378
* @return Resolved path
379
*/
380
fun resolve(child: Path, normalize: Boolean = false): Path
381
382
/**
383
* Creates a relative path from this path to another
384
* @param other Target path
385
* @return Relative path from this to other
386
*/
387
fun relativeTo(other: Path): Path
388
389
/**
390
* Returns a normalized version of this path
391
* Removes redundant segments like "." and ".."
392
* @return Normalized path
393
*/
394
fun normalized(): Path
395
396
/**
397
* Compares paths lexicographically
398
* @param other Path to compare with
399
* @return Comparison result
400
*/
401
override fun compareTo(other: Path): Int
402
403
/**
404
* Checks path equality
405
* @param other Object to compare with
406
* @return true if paths are equal
407
*/
408
override fun equals(other: Any?): Boolean
409
410
/**
411
* Returns hash code for the path
412
* @return Hash code value
413
*/
414
override fun hashCode(): Int
415
416
/**
417
* Returns string representation of the path
418
* @return Path as string using platform separators
419
*/
420
override fun toString(): String
421
422
companion object {
423
/**
424
* Platform-specific directory separator
425
*/
426
val DIRECTORY_SEPARATOR: String
427
}
428
}
429
430
/**
431
* Converts a string to a Path
432
* @param normalize Whether to normalize the resulting path
433
* @return Path representing the string
434
*/
435
fun String.toPath(normalize: Boolean = false): Path
436
```
437
438
**Usage Examples:**
439
440
```kotlin
441
// Creating paths
442
val home = "/home/user".toPath()
443
val file = home / "documents" / "file.txt"
444
val relative = "docs/readme.md".toPath()
445
446
// Path properties
447
println(file.name) // "file.txt"
448
println(file.parent) // "/home/user/documents"
449
println(file.isAbsolute) // true
450
println(relative.isRelative) // true
451
452
// Path operations
453
val normalized = "/home/user/../user/docs/./file.txt".toPath().normalized()
454
val relativePath = file.relativeTo(home) // "documents/file.txt"
455
```
456
457
### FileMetadata
458
459
Information about files and directories.
460
461
```kotlin { .api }
462
/**
463
* Metadata about a file or directory
464
* Contains information like size, type, and timestamps
465
*/
466
data class FileMetadata(
467
/**
468
* True if this is a regular file
469
*/
470
val isRegularFile: Boolean,
471
472
/**
473
* True if this is a directory
474
*/
475
val isDirectory: Boolean,
476
477
/**
478
* Target path if this is a symbolic link, null otherwise
479
*/
480
val symlinkTarget: Path?,
481
482
/**
483
* File size in bytes, null if not available
484
*/
485
val size: Long?,
486
487
/**
488
* Creation time in milliseconds since epoch, null if not available
489
*/
490
val createdAtMillis: Long?,
491
492
/**
493
* Last modification time in milliseconds since epoch, null if not available
494
*/
495
val lastModifiedAtMillis: Long?,
496
497
/**
498
* Last access time in milliseconds since epoch, null if not available
499
*/
500
val lastAccessedAtMillis: Long?,
501
502
/**
503
* Platform-specific extra metadata
504
*/
505
val extras: Map<KClass<*>, Any> = emptyMap()
506
) {
507
/**
508
* Gets typed extra metadata
509
* @param type Class type of the extra metadata
510
* @return Extra metadata of the specified type, or null
511
*/
512
fun <T : Any> extra(type: KClass<out T>): T?
513
514
/**
515
* Creates a copy with modified properties
516
*/
517
fun copy(
518
isRegularFile: Boolean = this.isRegularFile,
519
isDirectory: Boolean = this.isDirectory,
520
symlinkTarget: Path? = this.symlinkTarget,
521
size: Long? = this.size,
522
createdAtMillis: Long? = this.createdAtMillis,
523
lastModifiedAtMillis: Long? = this.lastModifiedAtMillis,
524
lastAccessedAtMillis: Long? = this.lastAccessedAtMillis,
525
extras: Map<KClass<*>, Any> = this.extras
526
): FileMetadata
527
}
528
```
529
530
**Usage Examples:**
531
532
```kotlin
533
val fs = FileSystem.SYSTEM
534
val path = "/tmp/example.txt".toPath()
535
536
// Create file and get metadata
537
fs.write(path) { writeUtf8("Hello") }
538
val metadata = fs.metadata(path)
539
540
println("Is file: ${metadata.isRegularFile}")
541
println("Size: ${metadata.size} bytes")
542
println("Modified: ${metadata.lastModifiedAtMillis}")
543
544
// Check if path exists
545
if (fs.exists(path)) {
546
println("File exists")
547
}
548
549
// List directory contents
550
val dir = "/tmp".toPath()
551
fs.list(dir).forEach { child ->
552
val childMetadata = fs.metadataOrNull(child)
553
println("${child.name}: ${childMetadata?.size ?: "unknown"} bytes")
554
}
555
```