Mark
12/24/2024, 2:31 PMPath.canRead()
and Path.canWrite()
when using okio? (note: some extension functions like Path.isDirectory()
are not shown for brevity (see thread).Mark
12/24/2024, 2:32 PMfun Path.canRead(): Boolean {
return try {
if (this.isDirectory()) {
this.listFiles()
} else {
FileSystem.SYSTEM.source(this).close() // Attempt to open for a file
}
true
} catch (e: Exception) {
println("path not readable: $this")
false
}
}
fun Path.canWrite(): Boolean {
return try {
if (this.isDirectory()) {
val tempFile = this / currentEpochMillis().toString()
try {
FileSystem.SYSTEM.sink(tempFile).close()
} finally {
tempFile.delete() // Cleanup after test
}
} else {
FileSystem.SYSTEM.sink(this).close()
}
true
} catch (e: Exception) {
println("path not writable: $this")
false
}
}
jessewilson
12/24/2024, 2:40 PMjessewilson
12/24/2024, 2:41 PMjessewilson
12/24/2024, 2:42 PMjessewilson
12/24/2024, 2:42 PMMark
12/24/2024, 2:42 PMMark
12/24/2024, 2:47 PMexternalFilesDir
can’t be used for some reason, so it determines that before proceeding with unpacking zips etc. So, as you suggest, I could just proceed with the unpacking first, and then should a problem arise, fallback to other install locations.Mark
12/25/2024, 2:36 AMFileSystem
was passed in: fun File.canRead(fs: FileSystem): Boolean
?jessewilson
12/25/2024, 3:31 AMjessewilson
12/25/2024, 3:32 AMjessewilson
12/25/2024, 3:33 AMMark
12/25/2024, 3:36 AMjessewilson
12/25/2024, 5:30 AMjessewilson
12/25/2024, 5:31 AMMark
12/25/2024, 5:46 AMMark
12/25/2024, 9:23 AMAssetManager.ACCESS_RANDOM
presumably it doesn’t make sense to use Source.buffer()
? I see there’s no RandomAccessSource
and so the only way I can see is to use a BufferedSource
with skip?jessewilson
12/25/2024, 9:33 PMAssetManager.asFileSystem()
with the okio-assetfilesystem
dep
https://github.com/square/okio/tree/master/okio-assetfilesystemMark
12/26/2024, 5:59 AMaccessMode
is just always being used as default (AssetManager.ACCESS_STREAMING
). Wouldn’t AssetManager.ACCESS_RANDOM
be useful for accessing individual files within a large zip file stored in assets, for example?jessewilson
12/26/2024, 5:53 PMMark
12/27/2024, 2:29 AMMark
12/27/2024, 2:39 AMFileSystem.rootedAt(directory: Path): FileSystem
extension function, which essentially just maps all incoming and outgoing paths? Often, when processing files in a directory (possibly with nested directories), you don’t care where it is located in a filesystem. Otherwise you have to pass around both the directory and FileSystem
.jessewilson
12/27/2024, 3:18 AMjessewilson
12/27/2024, 3:20 AMMark
12/27/2024, 4:07 AMMark
12/27/2024, 4:18 AMFileSystem
that auto-resolves ZIP files within it.Mark
12/27/2024, 4:32 AMbuildDirectory(rootDirectory) { // or maybe buildFileSystem()
file("foo.txt") { sink ->
...
}
directory("bar") {
file("baz.txt") { sink ->
...
}
zipFile("qux.zip") { zipOutputStream ->
}
}
}
jessewilson
12/27/2024, 5:11 AMjessewilson
12/27/2024, 5:12 AM.zip
file
https://github.com/square/okio/issues/1442#issuecomment-1962387496Mark
12/27/2024, 6:29 AMbuildDirectory(rootDirectory) { // or maybe buildFileSystem()
file("foo.txt") { sink ->
...
}
directory("bar") {
file("baz.txt") { sink ->
...
}
zipFile("qux.zip") { zipOutputStream ->
file("foo2.txt") { sink ->
...
}
directory("bar2") {
file("baz2.txt") { sink ->
...
}
}
}
}
}
Mark
12/28/2024, 3:19 AMFileSystem
with a Path
. Have you looked into having a class that wraps that pair? Perhaps:
class UniversalPath(val path: Path, private val fileSystem: FileSystem) {
fun exists(): Boolean ...
fun listPaths(): List<UniversalPath> ...
fun incarcerate(): FileSystem // naming subject to change
}
jessewilson
12/29/2024, 2:51 AMjessewilson
12/29/2024, 2:52 AMjessewilson
12/29/2024, 2:53 AMjessewilson
12/29/2024, 2:54 AMjessewilson
12/29/2024, 2:55 AMMark
12/29/2024, 3:51 AMUniversalPath
more as an extension of FileSystem
than Path
so in that sense, a service. Maybe it’s a naming problem. RootedFileSystem
instead, perhaps. I’m not seeing a huge difference between a FileSystem
that exposes the contents of a zip, with a FileSystem
(or UniversalPath
) that exposes the contents of a directory represented by a Path
. Going the value object way, you could have a Path
+ FileSystemIdentifier
. Where the latter could be encoded in the value string: assets:foo/bar.zip:qux/baz.xml
though I suppose this could end up conflicting with some platform-specific paths.jessewilson
12/29/2024, 1:15 PMinterface ScreenshotStore {
fun write(id: ScreenshotId, content: Screenshot)
fun list(): List<ScreenshotId>
fun read(id: ScreenshotId): Screenshot
}
jessewilson
12/29/2024, 1:16 PMMark
12/29/2024, 1:52 PMScreenshotStore
would be relatively trivial using the existing APIs, although you probably would still have implementations that have to deal with the three-filesystem situation mentioned earlier. No biggie I guess.Mark
12/30/2024, 3:21 AMDocumentFile
: https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile (which is more along the lines of UniversalPath
mentioned earlier) is because that is a more application-focussed interface. i.e. something that could be directly used in the implementation of ScreenshotStore
whereas it is not suitable to implement a FileSystem
because it only works on a given file/directory and so is not easily used to give results for an arbitrary Path
. Now I’m wondering how best to migrate away from DocumentFile
to a KMP alternative. At the moment, it looks like I need to write it to application cache storage and then use okio on that.jessewilson
12/30/2024, 4:39 AMjessewilson
12/30/2024, 4:41 AMMark
12/31/2024, 3:04 AMopenInputStream()
and then use ZipInputStream
to inspect the contents to see if it’s a ZIP file supported by the app. That sort of inspection isn’t really possible with okio (unless I’ve missed something) because FileSystem.openZip()
works with a Path
not a Source
. So that means having to first write the Source
to local cache just so that we have a Path
.jessewilson
12/31/2024, 8:43 AMjessewilson
12/31/2024, 8:43 AMjessewilson
12/31/2024, 8:47 AMMark
12/31/2024, 8:49 AMjessewilson
12/31/2024, 8:49 AMjessewilson
12/31/2024, 8:50 AMjessewilson
12/31/2024, 8:51 AMjessewilson
12/31/2024, 8:52 AMjessewilson
12/31/2024, 8:53 AMjessewilson
12/31/2024, 9:04 AMMark
12/31/2024, 9:29 AM