Просмотр исходного кода

Merge pull request #2867 from ag2s20150909/rar7z

初步实现RAR,7ZIP解压
kunfei 3 лет назад
Родитель
Сommit
bd15f23ebb

+ 5 - 1
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"

+ 1 - 0
app/src/main/java/io/legado/app/help/JsExtensions.kt

@@ -564,6 +564,7 @@ interface JsExtensions : JsEncodeUtils {
         return null
     }
 
+
 //******************文件操作************************//
 
     /**

+ 79 - 0
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()
+    }
+}

+ 37 - 0
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()
+    }
+
+}

+ 55 - 0
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)
+            }
+        }
+    }
+}