Remove more java.io usage
This commit is contained in:
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('/')
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -11,6 +11,7 @@ dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user