diff --git a/app/build.gradle b/app/build.gradle index 8ab5ef776..eca03b2e2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -135,7 +135,7 @@ android { dependencies { compileOnly "com.android.tools.build:gradle:$agp_version" //noinspection GradleDependency,GradlePackageUpdate - coreLibraryDesugaring('com.android.tools:desugar_jdk_libs:2.0.2') + coreLibraryDesugaring('com.android.tools:desugar_jdk_libs_nio:2.0.2') testImplementation('junit:junit:4.13.2') androidTestImplementation('androidx.test:runner:1.5.2') androidTestImplementation('androidx.test.espresso:espresso-core:3.5.1') @@ -231,6 +231,10 @@ dependencies { //apache implementation('org.apache.commons:commons-text:1.10.0') + implementation 'org.apache.commons:commons-compress:1.22' + + //RAR + implementation 'com.github.junrar:junrar:7.5.4' //MarkDown def markwonVersion = "4.6.2" diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index 185bb2004..3ae189731 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -564,6 +564,7 @@ interface JsExtensions : JsEncodeUtils { return null } + //******************文件操作************************// /** diff --git a/app/src/main/java/io/legado/app/utils/ParcelFileDescriptorChannel.kt b/app/src/main/java/io/legado/app/utils/ParcelFileDescriptorChannel.kt new file mode 100644 index 000000000..064c113df --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/ParcelFileDescriptorChannel.kt @@ -0,0 +1,79 @@ +package io.legado.app.utils + +import android.annotation.SuppressLint +import android.os.ParcelFileDescriptor +import android.system.ErrnoException +import android.system.Os +import android.system.OsConstants +import java.io.IOException +import java.nio.ByteBuffer +import java.nio.channels.SeekableByteChannel + +@SuppressLint("NewApi") +class ParcelFileDescriptorChannel(private val pfd: ParcelFileDescriptor) : SeekableByteChannel { + @Throws(IOException::class) + override fun read(dst: ByteBuffer): Int { + return try { + Os.read(pfd.fileDescriptor, dst) + } catch (e: ErrnoException) { + throw RuntimeException(e) + } + } + + @Throws(IOException::class) + override fun write(src: ByteBuffer): Int { + return try { + Os.write(pfd.fileDescriptor, src) + } catch (e: ErrnoException) { + throw RuntimeException(e) + } + } + + @Throws(IOException::class) + override fun position(): Long { + return try { + Os.lseek(pfd.fileDescriptor, 0, OsConstants.SEEK_CUR) + } catch (e: ErrnoException) { + throw RuntimeException(e) + } + } + + @Throws(IOException::class) + override fun position(newPosition: Long): SeekableByteChannel { + try { + Os.lseek(pfd.fileDescriptor, newPosition, OsConstants.SEEK_SET) + } catch (e: ErrnoException) { + throw RuntimeException(e) + } + return this + } + + @Throws(IOException::class) + override fun size(): Long { + return try { + Os.fstat(pfd.fileDescriptor).st_size + } catch (e: ErrnoException) { + throw RuntimeException(e) + } + } + + @Throws(IOException::class) + override fun truncate(newSize: Long): SeekableByteChannel { + require(!(newSize < 0L || newSize > Int.MAX_VALUE)) { "Size has to be in range 0.. " + Int.MAX_VALUE } + try { + Os.ftruncate(pfd.fileDescriptor, newSize) + } catch (e: ErrnoException) { + throw RuntimeException(e) + } + return this + } + + override fun isOpen(): Boolean { + return pfd.fileDescriptor.valid() + } + + @Throws(IOException::class) + override fun close() { + pfd.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/RarUtils.kt b/app/src/main/java/io/legado/app/utils/RarUtils.kt new file mode 100644 index 000000000..ac3cc8582 --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/RarUtils.kt @@ -0,0 +1,37 @@ +package io.legado.app.utils + +import com.github.junrar.Archive +import com.github.junrar.rarfile.FileHeader +import java.io.File +import java.io.FileOutputStream +import java.io.InputStream +@Suppress("unused") +object RarUtils { + fun unRarToPath(inputStream: InputStream, path: String){ + val archive= Archive(inputStream) + var entry: FileHeader + while (archive.nextFileHeader().also { entry=it }!=null){ + val entryFile = File(path, entry.fileName) + if (entry.isDirectory) { + if (!entryFile.exists()) { + entryFile.mkdirs() + } + continue + } + if (entryFile.parentFile?.exists() != true) { + entryFile.parentFile?.mkdirs() + } + if (!entryFile.exists()) { + entryFile.createNewFile() + entryFile.setReadable(true) + entryFile.setExecutable(true) + } + FileOutputStream(entryFile).use { + archive.getInputStream(entry).copyTo(it) + } + + } + inputStream.close() + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/SevenZipUtils.kt b/app/src/main/java/io/legado/app/utils/SevenZipUtils.kt new file mode 100644 index 000000000..6c5be50ac --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/SevenZipUtils.kt @@ -0,0 +1,55 @@ +package io.legado.app.utils + +import android.annotation.SuppressLint +import android.os.ParcelFileDescriptor +import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry +import org.apache.commons.compress.archivers.sevenz.SevenZFile +import org.apache.commons.compress.utils.SeekableInMemoryByteChannel +import java.io.File +import java.io.FileOutputStream +import java.io.InputStream +import java.nio.channels.FileChannel +@Suppress("unused") +object SevenZipUtils { + + + + fun un7zToPath(inputStream: InputStream, path: String){ + un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())),path) + } + fun un7zToPath(pfd: ParcelFileDescriptor, path: String){ + un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)),path) + } + @SuppressLint("NewApi") + fun un7zToPath(fileChannel: FileChannel, path: String){ + un7zToPath(SevenZFile(fileChannel),path) + } + fun un7zToPath(file: File, path: String){ + un7zToPath(SevenZFile(file),path) + } + + + fun un7zToPath(sevenZFile:SevenZFile, path: String){ + var entry: SevenZArchiveEntry + while (sevenZFile.nextEntry.also { entry=it }!=null){ + val entryFile = File(path, entry.name) + if (entry.isDirectory) { + if (!entryFile.exists()) { + entryFile.mkdirs() + } + continue + } + if (entryFile.parentFile?.exists() != true) { + entryFile.parentFile?.mkdirs() + } + if (!entryFile.exists()) { + entryFile.createNewFile() + entryFile.setReadable(true) + entryFile.setExecutable(true) + } + FileOutputStream(entryFile).use { + sevenZFile.getInputStream(entry).copyTo(it) + } + } + } +} \ No newline at end of file