A modern I/O library that complements java.io and java.nio to make it much easier to access, store, and process your data.
—
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.
Core file system operations for cross-platform file access.
/**
* Read/write access to a hierarchical file collection
* Provides cross-platform file system operations
*/
abstract class FileSystem : Closeable {
/**
* Resolves path to canonical form, following symlinks
* @param path Path to canonicalize
* @return Canonical path
* @throws IOException if path resolution fails
*/
@Throws(IOException::class)
abstract fun canonicalize(path: Path): Path
/**
* Gets metadata for the file or directory at path
* @param path Path to get metadata for
* @return FileMetadata describing the file
* @throws FileNotFoundException if path doesn't exist
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun metadata(path: Path): FileMetadata
/**
* Gets metadata for the file or directory at path, or null if not found
* @param path Path to get metadata for
* @return FileMetadata describing the file, or null if not found
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun metadataOrNull(path: Path): FileMetadata?
/**
* Checks if a file or directory exists at path
* @param path Path to check
* @return true if path exists
*/
fun exists(path: Path): Boolean
/**
* Lists the contents of a directory
* @param dir Directory path to list
* @return List of paths in the directory
* @throws FileNotFoundException if directory doesn't exist
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun list(dir: Path): List<Path>
/**
* Lists the contents of a directory, or null if not found
* @param dir Directory path to list
* @return List of paths in the directory, or null if not found
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun listOrNull(dir: Path): List<Path>?
/**
* Recursively lists all files and directories
* @param dir Directory to start listing from
* @param followSymlinks Whether to follow symbolic links
* @return Sequence of all nested paths
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
fun listRecursively(dir: Path, followSymlinks: Boolean = false): Sequence<Path>
/**
* Opens a file for reading
* @param file Path to file to open
* @return Source for reading the file
* @throws FileNotFoundException if file doesn't exist
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun source(file: Path): Source
/**
* Opens a file for writing
* @param file Path to file to open
* @param mustCreate If true, fails if file already exists
* @return Sink for writing to the file
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun sink(file: Path, mustCreate: Boolean = false): Sink
/**
* Opens a file for appending
* @param file Path to file to open
* @param mustExist If true, fails if file doesn't exist
* @return Sink for appending to the file
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun appendingSink(file: Path, mustExist: Boolean = true): Sink
/**
* Opens a file for random access reading
* @param file Path to file to open
* @return FileHandle for random access
* @throws FileNotFoundException if file doesn't exist
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun openReadOnly(file: Path): FileHandle
/**
* Opens a file for random access reading and writing
* @param file Path to file to open
* @param mustCreate If true, fails if file already exists
* @param mustExist If true, fails if file doesn't exist
* @return FileHandle for random access
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
abstract fun openReadWrite(
file: Path,
mustCreate: Boolean = false,
mustExist: Boolean = false
): FileHandle
/**
* Creates a directory
* @param dir Directory path to create
* @param mustCreate If true, fails if directory already exists
* @throws IOException if creation fails
*/
@Throws(IOException::class)
abstract fun createDirectory(dir: Path, mustCreate: Boolean = false)
/**
* Creates a directory and all necessary parent directories
* @param dir Directory path to create
* @param mustCreate If true, fails if directory already exists
* @throws IOException if creation fails
*/
@Throws(IOException::class)
fun createDirectories(dir: Path, mustCreate: Boolean = false)
/**
* Atomically moves a file or directory
* @param source Source path
* @param target Target path
* @throws IOException if move fails
*/
@Throws(IOException::class)
abstract fun atomicMove(source: Path, target: Path)
/**
* Copies a file
* @param source Source file path
* @param target Target file path
* @throws IOException if copy fails
*/
@Throws(IOException::class)
fun copy(source: Path, target: Path)
/**
* Deletes a file or empty directory
* @param path Path to delete
* @param mustExist If true, fails if path doesn't exist
* @throws IOException if deletion fails
*/
@Throws(IOException::class)
abstract fun delete(path: Path, mustExist: Boolean = true)
/**
* Recursively deletes a file or directory
* @param fileOrDirectory Path to delete
* @param mustExist If true, fails if path doesn't exist
* @throws IOException if deletion fails
*/
@Throws(IOException::class)
fun deleteRecursively(fileOrDirectory: Path, mustExist: Boolean = true)
/**
* Creates a symbolic link
* @param source Link path to create
* @param target Target path the link points to
* @throws IOException if link creation fails
*/
@Throws(IOException::class)
abstract fun createSymlink(source: Path, target: Path)
/**
* Closes the file system and releases resources
* @throws IOException if an error occurs during closing
*/
@Throws(IOException::class)
override fun close()
companion object {
/**
* The system's default file system
*/
val SYSTEM: FileSystem
/**
* Path to the system's temporary directory
*/
val SYSTEM_TEMPORARY_DIRECTORY: Path
}
}Convenient methods for simple file read/write operations.
/**
* Reads a file and executes the given block with a BufferedSource
* @param file Path to file to read
* @param readerAction Block to execute with BufferedSource
* @return Result of the reader action
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
inline fun <T> FileSystem.read(file: Path, readerAction: BufferedSource.() -> T): T
/**
* Writes to a file and executes the given block with a BufferedSink
* @param file Path to file to write
* @param mustCreate If true, fails if file already exists
* @param writerAction Block to execute with BufferedSink
* @return Result of the writer action
* @throws IOException if an I/O error occurs
*/
@Throws(IOException::class)
inline fun <T> FileSystem.write(
file: Path,
mustCreate: Boolean = false,
writerAction: BufferedSink.() -> T
): TUsage Examples:
val fs = FileSystem.SYSTEM
val path = "/tmp/example.txt".toPath()
// Simple file operations
fs.write(path) {
writeUtf8("Hello, World!")
}
val content = fs.read(path) {
readUtf8()
}
println(content) // "Hello, World!"
// Directory operations
val dir = "/tmp/example_dir".toPath()
fs.createDirectory(dir)
fs.list(dir).forEach { println(it) }
// File metadata
val metadata = fs.metadata(path)
println("Size: ${metadata.size}")
println("Is file: ${metadata.isRegularFile}")Cross-platform path manipulation and navigation.
/**
* Hierarchical address on a filesystem
* Provides cross-platform path manipulation
*/
class Path private constructor() : Comparable<Path> {
/**
* Root path if this is absolute, null if relative
*/
val root: Path?
/**
* List of path segments (directory and file names)
*/
val segments: List<String>
/**
* Path segments as ByteString instances
*/
val segmentsBytes: List<ByteString>
/**
* True if this is an absolute path
*/
val isAbsolute: Boolean
/**
* True if this is a relative path
*/
val isRelative: Boolean
/**
* Windows drive letter, or null on other platforms
*/
val volumeLetter: Char?
/**
* Name of the final segment (file or directory name)
*/
val name: String
/**
* Name of the final segment as ByteString
*/
val nameBytes: ByteString
/**
* Parent directory path, or null if this is a root
*/
val parent: Path?
/**
* True if this path represents a root directory
*/
val isRoot: Boolean
/**
* Resolves a relative path against this path
* @param child Relative path or filename to resolve
* @return New path with child appended
*/
operator fun div(child: String): Path
/**
* Resolves a relative path against this path
* @param child ByteString path to resolve
* @return New path with child appended
*/
operator fun div(child: ByteString): Path
/**
* Resolves a path against this path
* @param child Path to resolve
* @return Resolved path
*/
operator fun div(child: Path): Path
/**
* Resolves a path with optional normalization
* @param child Child path to resolve
* @param normalize Whether to normalize the result
* @return Resolved path
*/
fun resolve(child: String, normalize: Boolean = false): Path
/**
* Resolves a ByteString path with optional normalization
* @param child Child path to resolve
* @param normalize Whether to normalize the result
* @return Resolved path
*/
fun resolve(child: ByteString, normalize: Boolean = false): Path
/**
* Resolves a path with optional normalization
* @param child Child path to resolve
* @param normalize Whether to normalize the result
* @return Resolved path
*/
fun resolve(child: Path, normalize: Boolean = false): Path
/**
* Creates a relative path from this path to another
* @param other Target path
* @return Relative path from this to other
*/
fun relativeTo(other: Path): Path
/**
* Returns a normalized version of this path
* Removes redundant segments like "." and ".."
* @return Normalized path
*/
fun normalized(): Path
/**
* Compares paths lexicographically
* @param other Path to compare with
* @return Comparison result
*/
override fun compareTo(other: Path): Int
/**
* Checks path equality
* @param other Object to compare with
* @return true if paths are equal
*/
override fun equals(other: Any?): Boolean
/**
* Returns hash code for the path
* @return Hash code value
*/
override fun hashCode(): Int
/**
* Returns string representation of the path
* @return Path as string using platform separators
*/
override fun toString(): String
companion object {
/**
* Platform-specific directory separator
*/
val DIRECTORY_SEPARATOR: String
}
}
/**
* Converts a string to a Path
* @param normalize Whether to normalize the resulting path
* @return Path representing the string
*/
fun String.toPath(normalize: Boolean = false): PathUsage Examples:
// Creating paths
val home = "/home/user".toPath()
val file = home / "documents" / "file.txt"
val relative = "docs/readme.md".toPath()
// Path properties
println(file.name) // "file.txt"
println(file.parent) // "/home/user/documents"
println(file.isAbsolute) // true
println(relative.isRelative) // true
// Path operations
val normalized = "/home/user/../user/docs/./file.txt".toPath().normalized()
val relativePath = file.relativeTo(home) // "documents/file.txt"Information about files and directories.
/**
* Metadata about a file or directory
* Contains information like size, type, and timestamps
*/
data class FileMetadata(
/**
* True if this is a regular file
*/
val isRegularFile: Boolean,
/**
* True if this is a directory
*/
val isDirectory: Boolean,
/**
* Target path if this is a symbolic link, null otherwise
*/
val symlinkTarget: Path?,
/**
* File size in bytes, null if not available
*/
val size: Long?,
/**
* Creation time in milliseconds since epoch, null if not available
*/
val createdAtMillis: Long?,
/**
* Last modification time in milliseconds since epoch, null if not available
*/
val lastModifiedAtMillis: Long?,
/**
* Last access time in milliseconds since epoch, null if not available
*/
val lastAccessedAtMillis: Long?,
/**
* Platform-specific extra metadata
*/
val extras: Map<KClass<*>, Any> = emptyMap()
) {
/**
* Gets typed extra metadata
* @param type Class type of the extra metadata
* @return Extra metadata of the specified type, or null
*/
fun <T : Any> extra(type: KClass<out T>): T?
/**
* Creates a copy with modified properties
*/
fun copy(
isRegularFile: Boolean = this.isRegularFile,
isDirectory: Boolean = this.isDirectory,
symlinkTarget: Path? = this.symlinkTarget,
size: Long? = this.size,
createdAtMillis: Long? = this.createdAtMillis,
lastModifiedAtMillis: Long? = this.lastModifiedAtMillis,
lastAccessedAtMillis: Long? = this.lastAccessedAtMillis,
extras: Map<KClass<*>, Any> = this.extras
): FileMetadata
}Usage Examples:
val fs = FileSystem.SYSTEM
val path = "/tmp/example.txt".toPath()
// Create file and get metadata
fs.write(path) { writeUtf8("Hello") }
val metadata = fs.metadata(path)
println("Is file: ${metadata.isRegularFile}")
println("Size: ${metadata.size} bytes")
println("Modified: ${metadata.lastModifiedAtMillis}")
// Check if path exists
if (fs.exists(path)) {
println("File exists")
}
// List directory contents
val dir = "/tmp".toPath()
fs.list(dir).forEach { child ->
val childMetadata = fs.metadataOrNull(child)
println("${child.name}: ${childMetadata?.size ?: "unknown"} bytes")
}Install with Tessl CLI
npx tessl i tessl/maven-com-squareup-okio--okio-jvm