Remove more java.io usage

This commit is contained in:
FooIbar committed 2024-12-13 11:51:48 +08:00
1 parent 41decf85c9
commit de5d74a1f0
11 files changed
+77 -77

No files matched your search

@@ -16,8 +16,9 @@ import com.hippo.ehviewer.client.data.TagNamespace.Male
import com.hippo.ehviewer.client.data.TagNamespace.Mixed
import com.hippo.ehviewer.client.data.TagNamespace.Other
import com.hippo.ehviewer.client.data.TagNamespace.Parody
import com.hippo.files.inputStream
import com.hippo.files.outputStream
import com.hippo.ehviewer.ui.screen.implicit
import com.hippo.files.read
import com.hippo.files.write
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -25,12 +26,12 @@ import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import net.devrieze.xmlutil.serialization.kxio.decodeFromSource
import net.devrieze.xmlutil.serialization.kxio.encodeToSink
import nl.adaptivity.xmlutil.XmlDeclMode
import nl.adaptivity.xmlutil.core.XmlVersion
import nl.adaptivity.xmlutil.newWriter
import nl.adaptivity.xmlutil.serialization.XML
import nl.adaptivity.xmlutil.serialization.XmlElement
import nl.adaptivity.xmlutil.xmlStreaming
import okio.Path
const val COMIC_INFO_FILE = "ComicInfo.xml"
@@ -107,18 +108,14 @@ fun ComicInfo.toSimpleTags() = listOfNotNull(
).flatten().ifEmpty { null }
fun ComicInfo.write(file: Path) {
file.outputStream().bufferedWriter().use {
xmlStreaming.newWriter(it).use { writer ->
xml.encodeToWriter(writer, ComicInfo.serializer(), this)
}
file.write {
xml.encodeToSink(this, implicit<ComicInfo>())
}
}
fun readComicInfo(file: Path): ComicInfo? = runCatching {
file.inputStream().bufferedReader().use {
xmlStreaming.newReader(it).use { reader ->
xml.decodeFromReader(ComicInfo.serializer(), reader)
}
file.read {
xml.decodeFromSource<ComicInfo>(this)
}
}.getOrNull()
@@ -39,6 +39,7 @@ import com.hippo.ehviewer.download.tempDownloadDir
import com.hippo.ehviewer.image.PathSource
import com.hippo.ehviewer.jni.archiveFdBatch
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.copyTo
import com.hippo.ehviewer.util.sendTo
import com.hippo.ehviewer.util.sha1
import com.hippo.files.delete
@@ -49,7 +50,6 @@ import com.hippo.files.list
import com.hippo.files.mkdirs
import com.hippo.files.moveTo
import com.hippo.files.openFileDescriptor
import com.hippo.files.outputStream
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.plugins.onDownload
import io.ktor.client.plugins.timeout
@@ -221,9 +221,7 @@ class SpiderDen(val info: GalleryInfo) {
val url = response.request.url.toString()
val extension = MimeTypeMap.getFileExtensionFromUrl(url).ifEmpty { "jpg" }
return saveResponseMeta(index, extension) { outFile ->
outFile.outputStream().use {
response.bodyAsChannel().copyTo(it.channel)
}
response.bodyAsChannel().copyTo(outFile)
FileHashRegex.find(url)?.let {
val expected = it.groupValues[1]
val actual = outFile.sha1()
@@ -4,8 +4,8 @@ import com.hippo.ehviewer.coil.edit
import com.hippo.ehviewer.coil.read
import com.hippo.ehviewer.ktbuilder.diskCache
import com.hippo.ehviewer.legacy.readLegacySpiderInfo
import com.hippo.files.outputStream
import com.hippo.files.read
import com.hippo.files.write
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.io.readByteArray
import kotlinx.serialization.Serializable
@@ -37,15 +37,13 @@ private val cbor = Cbor {
}
fun SpiderInfo.write(file: Path) {
file.outputStream().use {
it.write(cbor.encodeToByteArray(this))
}
file.write { write(cbor.encodeToByteArray(this)) }
}
fun SpiderInfo.saveToCache() {
runSuspendCatching {
spiderInfoCache.edit(gid.toString()) {
data.toFile().writeBytes(cbor.encodeToByteArray(this@saveToCache))
data.write { write(cbor.encodeToByteArray(this@saveToCache)) }
}
}.onFailure {
logcat(it)
@@ -67,8 +67,9 @@ import com.hippo.ehviewer.util.requestPermission
import com.hippo.ehviewer.util.toEpochMillis
import com.hippo.ehviewer.util.toLocalDateTime
import com.hippo.files.delete
import com.hippo.files.exists
import com.hippo.files.isDirectory
import com.hippo.files.outputStream
import com.hippo.files.write
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.lang.withUIContext
@@ -89,7 +90,7 @@ private fun removeNoMediaFile(downloadDir: Path) {
}
private fun ensureNoMediaFile(downloadDir: Path) {
(downloadDir / ".nomedia").outputStream().close()
(downloadDir / ".nomedia").apply { if (!exists()) write {} }
}
private val lck = Mutex()
@@ -7,7 +7,7 @@ import com.hippo.ehviewer.client.executeAndParseAs
import com.hippo.ehviewer.client.executeSafely
import com.hippo.ehviewer.util.copyTo
import com.hippo.ehviewer.util.ensureSuccess
import com.hippo.files.outputStream
import com.hippo.files.write
import io.ktor.client.plugins.timeout
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.header
@@ -18,6 +18,7 @@ import java.util.zip.ZipInputStream
import kotlin.time.Duration.Companion.days
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.io.asSource
import moe.tarsin.coroutines.runSuspendCatching
import okio.Path
import tachiyomi.data.release.GithubArtifacts
@@ -79,9 +80,7 @@ object AppUpdater {
response.bodyAsChannel().toInputStream().use { stream ->
ZipInputStream(stream).use { zip ->
zip.nextEntry
path.outputStream().use {
zip.copyTo(it)
}
path.write { transferFrom(zip.asSource()) }
}
}
} else {
@@ -1,35 +1,6 @@
package com.hippo.ehviewer.util
import android.os.Build
import android.system.Int64Ref
import android.system.Os
import androidx.annotation.RequiresApi
import com.hippo.files.inputStream
import com.hippo.files.openFileDescriptor
import com.hippo.files.outputStream
import eu.kanade.tachiyomi.util.system.logcat
import java.io.FileDescriptor
import com.hippo.files.SystemFileSystem
import okio.Path
@RequiresApi(Build.VERSION_CODES.P)
private fun sendFileTotally(from: FileDescriptor, to: FileDescriptor): Long = Os.sendfile(to, from, Int64Ref(0), Long.MAX_VALUE)
infix fun Path.sendTo(file: Path): Long {
if (isAtLeastP) {
// sendfile may fail on some devices
try {
return openFileDescriptor("r").use { src ->
file.openFileDescriptor("wt").use { dst ->
sendFileTotally(src.fileDescriptor, dst.fileDescriptor)
}
}
} catch (e: Exception) {
logcat("sendfile", e)
}
}
return inputStream().use { src ->
file.outputStream().use { dst ->
src.channel.transferTo(0, Long.MAX_VALUE, dst.channel)
}
}
}
infix fun Path.sendTo(file: Path) = SystemFileSystem.copy(this, file)
@@ -15,9 +15,10 @@
*/
package com.hippo.ehviewer.util
import com.hippo.files.outputStream
import com.hippo.files.write
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.copyTo
import io.ktor.utils.io.InternalAPI
import io.ktor.utils.io.rethrowCloseCauseIfNeeded
import java.io.File
import java.util.Locale
import kotlin.math.ln
@@ -125,8 +126,13 @@ object FileUtils {
fun getNameFromFilename(filename: String?) = filename?.substringBeforeLast('.')?.ifEmpty { null }
}
@OptIn(InternalAPI::class)
suspend fun ByteReadChannel.copyTo(file: Path) {
file.outputStream().use {
copyTo(it.channel)
file.write {
while (!isClosedForRead) {
transferFrom(readBuffer)
awaitContent()
}
rethrowCloseCauseIfNeeded()
}
}
@@ -7,8 +7,13 @@ import android.os.ParcelFileDescriptor
import android.provider.DocumentsContract
import android.provider.DocumentsContract.Document
import android.provider.MediaStore
import android.system.ErrnoException
import android.system.Int64Ref
import android.system.Os
import android.webkit.MimeTypeMap
import androidx.core.database.getLongOrNull
import kotlinx.io.asSink
import kotlinx.io.asSource
import okio.FileHandle
import okio.FileMetadata
import okio.FileNotFoundException
@@ -16,8 +21,7 @@ import okio.FileSystem
import okio.IOException
import okio.Path
import okio.Sink
import okio.sink
import okio.source
import okio.Source
import splitties.init.appCtx
class AndroidFileSystem(context: Context) : FileSystem() {
@@ -48,6 +52,26 @@ class AndroidFileSystem(context: Context) : FileSystem() {
TODO("Not yet implemented")
}
override fun copy(source: Path, target: Path) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
source.openFileDescriptor("r").use { src ->
target.openFileDescriptor("wt").use { dst ->
try {
Os.sendfile(dst.fileDescriptor, src.fileDescriptor, Int64Ref(0), Long.MAX_VALUE)
return
} catch (_: ErrnoException) {}
}
}
}
// Fallback to transferTo if sendfile is not available or fails
source.inputStream().use { src ->
target.outputStream().use { dst ->
src.channel.transferTo(0, Long.MAX_VALUE, dst.channel)
}
}
}
override fun createDirectory(dir: Path, mustCreate: Boolean) {
if (dir.isPhysicalFile()) {
return physicalFileSystem.createDirectory(dir, mustCreate)
@@ -177,11 +201,16 @@ class AndroidFileSystem(context: Context) : FileSystem() {
}
override fun sink(file: Path, mustCreate: Boolean): Sink {
if (mustCreate && exists(file)) throw IOException("$file already exists.")
return file.outputStream().sink()
TODO("Not yet implemented")
}
override fun source(file: Path) = file.inputStream().source()
override fun source(file: Path): Source {
TODO("Not yet implemented")
}
fun rawSink(file: Path) = file.outputStream().asSink()
fun rawSource(file: Path) = file.inputStream().asSource()
fun openFileDescriptor(path: Path, mode: String): ParcelFileDescriptor {
if (path.isPhysicalFile()) {
@@ -199,6 +228,10 @@ class AndroidFileSystem(context: Context) : FileSystem() {
contentResolver.openFileDescriptor(path.toUri(), mode)
}.getOrNull() ?: throw FileNotFoundException("Failed to open file: $path")
}
private fun Path.inputStream() = ParcelFileDescriptor.AutoCloseInputStream(openFileDescriptor(this, "r"))
private fun Path.outputStream() = ParcelFileDescriptor.AutoCloseOutputStream(openFileDescriptor(this, "wt"))
}
private fun Path.isPhysicalFile() = toString().startsWith('/')
+3 -8
View File
@@ -2,12 +2,9 @@ package com.hippo.files
import android.content.ContentResolver
import android.net.Uri
import android.os.ParcelFileDescriptor
import androidx.core.net.toUri
import java.io.FileInputStream
import java.io.FileOutputStream
import kotlinx.io.Sink
import kotlinx.io.Source
import kotlinx.io.asSource
import kotlinx.io.buffered
import okio.Path
import okio.Path.Companion.toPath
@@ -34,11 +31,9 @@ infix fun Path.moveTo(target: Path) = SystemFileSystem.atomicMove(this, target)
fun Path.openFileDescriptor(mode: String) = SystemFileSystem.openFileDescriptor(this, mode)
fun Path.inputStream(): FileInputStream = ParcelFileDescriptor.AutoCloseInputStream(SystemFileSystem.openFileDescriptor(this, "r"))
inline fun <T> Path.read(f: Source.() -> T) = SystemFileSystem.rawSource(this).buffered().use(f)
fun Path.outputStream(): FileOutputStream = ParcelFileDescriptor.AutoCloseOutputStream(SystemFileSystem.openFileDescriptor(this, "wt"))
inline fun <T> Path.read(f: Source.() -> T) = inputStream().asSource().buffered().use(f)
inline fun <T> Path.write(f: Sink.() -> T) = SystemFileSystem.rawSink(this).buffered().use(f)
fun Path.toUri(): Uri {
val str = toString()
+3 -2
View File
@@ -30,7 +30,7 @@ okhttp = "5.0.0-alpha.14"
okio = "3.9.1"
splitties = "3.0.0"
telephoto = "0.14.0"
xmlutil = "0.90.3"
xmlutil = "0.90.4-SNAPSHOT"
junit = "1.2.1"
uiautomator = "2.4.0-alpha01"
benchmark = "1.4.0-alpha06"
@@ -112,6 +112,7 @@ serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-jso
serialization-json-io = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-io", version.ref = "kotlinx-serialization" }
serialization-xml = { module = "io.github.pdvrieze.xmlutil:serialization", version.ref = "xmlutil" }
serialization-xml-io = { module = "io.github.pdvrieze.xmlutil:serialization-io", version.ref = "xmlutil" }
splitties-appctx = { module = "com.louiscad.splitties:splitties-appctx", version.ref = "splitties" }
splitties-arch-room = { module = "com.louiscad.splitties:splitties-arch-room", version.ref = "splitties" }
@@ -129,7 +130,7 @@ androidx-profileinstaller = { module = "androidx.profileinstaller:profileinstall
arrow = ["arrow-fx-coroutines", "arrow-functions", "arrow-resilience"]
coil = ["coil-compose", "coil-gif", "coil-network"]
compose = ["compose-foundation", "compose-material-icons-extended", "compose-material3", "compose-material3-adaptive", "compose-ui-util"]
kotlinx-serialization = ["serialization-cbor", "serialization-json", "serialization-json-io", "serialization-xml"]
kotlinx-serialization = ["serialization-cbor", "serialization-json", "serialization-json-io", "serialization-xml", "serialization-xml-io"]
splitties = ["splitties-appctx", "splitties-arch-room", "splitties-preferences", "splitties-systemservices"]
[plugins]
+1
View File
@@ -11,6 +11,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
}