我们无法使用此KMP代码在iOS应用程序上成功写入数据. 我们想知道我们可以改变什么来使它成功地写入:

suspend fun HttpResponse.saveBodyToFile(fileSystem: FileSystem, outputFile: Path): Boolean {
    var success = false
    try {
        // if the target file already exists, remove it.
        fileSystem.delete(outputFile)

        val parentDir = outputFile.parent ?: return false
        if (!fileSystem.exists(parentDir)) {
            fileSystem.createDirectories(parentDir)
        }

        val byteReadChannel: ByteReadChannel = body()
        fileSystem.sink(outputFile).buffer().use {
            byteReadChannel.readFully(it)
        }

        success = fileSystem.exists(outputFile)
    } catch (e: KtorIoException) {
        Logger.e(e) { "Failed to save response stream to ${outputFile.name}" }
        Logger.e { "I/O Exception ${e.message}"}
       fileSystem.delete(outputFile)
    } catch (e: OkioIOException) {
        Logger.e { "I/O Exception ${e.message}"}
        Logger.e(e) { "Failed to save response stream to ${outputFile.name}" }
        Logger.e { "I/O Exception ${e.message}"}
        fileSystem.delete(outputFile)
    }
    return success
}

奇怪的是,它创建了一个目录,但抛出了这个错误: 🔴I/O异常只读文件系统

如果该目录已经存在,它仍然将其判断为True:

(!fileSystem.exists(parentDir))

并试图再次创造它.

如果该目录存在,并且这段代码被注释掉:

 if (!fileSystem.exists(parentDir)) {
    fileSystem.createDirectories(parentDir)
 }

那么这段代码:

fileSystem.sink(outputFile).buffer().use {
    byteReadChannel.readFully(it)
}

引发此错误: 🔴I/O异常只读文件系统

我们传入一个Cache目录的文件夹:

file:/Users/myname/Library/Developer/CoreSimulator/Devices/85FF4164-D3CF-446C-AF42-EC64B5473BCA/data/Containers/Data/Application/7F890ECD-83DB-4D91-8BBD-102F631594A6/Library/Caches/syncFiles/sync-proxy.json

推荐答案

因此,我们使用Okio进行KMP I/O操作.访问相应的目录

guard let cacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first?.appendingPathComponent("syncFiles")

而不是将cacheDirectory.absoluteString作为父目录传递给OKIO的文件系统.absoluteString返回格式为file:<path>的字符串

OKIO使用lstat来确定路径是否存在.lstat不支持URL格式的路径,而OKIO支持URL格式的文件路径.

当调用createDirectories时,它使用lstat向OKIO返回FALSE,并try 创建所有已存在的只读父目录,从而导致崩溃.

修复非常简单,不是调用cacheDirectory.absoluteString,而是将其更改为cacheDirectory.path(),这会正确地删除file:lstat报告.

Kotlin相关问答推荐

为什么";";.equals(1)在柯特林语中是有效的,但";";=1是无效的?

有没有一种简单的方法来识别物体?

Kotlin stlib中是否有用于将列表<;对<;A,B&>;转换为对<;列表<;A&>,列表<;B&>;的函数

如何定义一个函数来接受任何具有特定字段的数据类

collectAsState 未从存储库接收更改

如何创建扩展函数isNullOrEmpty?

从 Kotlin 调用 Java 时可以为空的规则是什么

关于 Kotlin 函数类型转换的问题

为空数组添加值

如何在 Kotlin for Android 上使用setTextColor(hexaValue),

.indices 在 kotlin 中的含义是什么?

如何禁用智能投射突出显示 Kotlin?

如何在MVVM架构中观察RecyclerView适配器中的LiveData?

launch 仅从 Kotlin 1.3 开始可用,不能在 Kotlin 1.2 中使用

Kotlin-通过与属性列表进行比较来筛选对象列表

如何捕获传递给模拟函数的参数并返回它?

Kotlin/JS,Gradle 插件:无法加载@webpack-cli/serve命令

Android Jetpack导航,另一个主机片段中的主机片段

Gradle:无法连接到 Windows 上的 Kotlin 守护程序

kotlin中的全局可拓函数