ktfs is a lightweight wrapper around kotlinx.io.files that fixes non-ASCII path handling on Windows.
It wraps the file system implementation of kotlinx-io except for mingwX64 target. Windows file system is re-implemented using platform.windows wide character APIs, fixing the issue that paths with non-ASCII characters (for example, Chinese characters) cannot be accessed via the original implementation.
kotlinx.io.files.Path() is the official way to create a path, which accepts vararg segments:
val path =Path("data", "notes", "today.txt")ktfs adds a few small helpers for building paths more fluently:
operatorfun Path.div(other:String): PathvalString.asPath:PathThese helpers are useful when you want to write path construction in a more DSL-like style. If you already have a Path, using / "child" is the clearest option. If you start from a string literal, prefer "root".asPath / "child".
importorg.ntqqrev.ktfs.asPathimportorg.ntqqrev.ktfs.divval root ="data".asPath /"notes"val today = root /"today.txt"val archive ="data".asPath /"archive"/"today.txt"inlinefun <R> withFs(fs:FileSystem = defaultFileSystem, block:FileSystem.() ->R): RYou can use withFs to execute a block of code with a specific file system implementation. By default, it uses the platform's default file system.
FileSystem introduces a set of extension properties and functions on Path that allow you to perform file system operations directly on Path instances. This design promotes a more fluent and intuitive way to work with file paths.
interfaceFileSystem {
valPath.exists:BooleanvalPath.metadataOrNull:FileMetadata?valPath.isDirectory:BooleanvalPath.isRegularFile:Booleanfun Path.createDirectories()
fun Path.createDirectoriesOrFail()
fun Path.delete()
fun Path.deleteIfExists(): Booleanfun Path.moveTo(destination:Path)
valPath.absolute:PathvalPath.children:Collection<Path>
fun Path.readText(): Stringfun Path.writeText(
text:String,
append:Boolean = false,
createParentDirectories:Boolean = false,
)
fun Path.readBytes(): ByteArrayfun Path.writeBytes(
bytes:ByteArray,
append:Boolean = false,
createParentDirectories:Boolean = false,
)
}You can use these functions directly in withFs block, and they will be dispatched to the appropriate file system implementation based on the platform.
importkotlinx.io.files.Pathimportorg.ntqqrev.ktfs.asPathimportorg.ntqqrev.ktfs.withFs
withFs {
val note ="data".asPath /"notes"/"today.txt"if (note.exists && note.isRegularFile) {
val archived ="data".asPath /"notes"/"today.done.txt" note.moveTo(archived)
}
note.writeText("hello", createParentDirectories =true)
}