【问题标题】:IndexOutOfBounds exception while trying to convert a folder contents into a zip file尝试将文件夹内容转换为 zip 文件时出现 IndexOutOfBounds 异常
【发布时间】:2018-09-13 13:35:52
【问题描述】:

我有一个要求,我有两个文件夹,每个文件夹都必须转换为各自的 zip 文件。这是我正在使用的当前代码。

fun zipFolder(inputFolderPath: String, outZipPath: String) {
    try {
        val fos = FileOutputStream(outZipPath)
        val zos = ZipOutputStream(fos)
        val srcFile = File(inputFolderPath)
        if (!srcFile.exists()) {
            Timber.e("Src file ${srcFile.path} does not exist..")
            return
        }
        val files = srcFile.listFiles()
        Timber.d("Zip directory: " + srcFile.name)
        for (i in files.indices) {
            Log.d("", "Adding file: " + files[i].name)
            val buffer = ByteArray(2048)
            val fis = FileInputStream(files[i])
            zos.putNextEntry(ZipEntry(files[i].name))
            while (fis.read(buffer) > 0) {
                zos.write(buffer, 0, fis.read(buffer))
            }
            zos.closeEntry()
            fis.close()
        }
        zos.close()
    } catch (e: IOException) {
        Timber.e(e)
    }

}

但由于某种原因,我在此过程中遇到了 IndexOutOfBounds 异常。

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=234, result=-1, data=Intent { cmp=proj.com.wimwiiftkagent/proj.com.inspection.ui.InspectionProcedureActivity (has extras) }} to activity {proj.com.wimwiiftkagent/proj.com.wimwiiftkagent.ui.inspection.InspectionActivity}: java.lang.IndexOutOfBoundsException
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4440)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4484)
        at android.app.ActivityThread.-wrap19(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1743)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6753)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: java.lang.IndexOutOfBoundsException
        at java.util.zip.ZipOutputStream.write(ZipOutputStream.java:322)
        at proj.com.wimwiiftkagent.utils.FileUtils.zipFolder(FileUtils.kt:31)
        at proj.com.wimwiiftkagent.ui.inspection.InspectionActivity.processInspectionData(InspectionActivity.kt:59)
        at proj.com.wimwiiftkagent.ui.inspection.InspectionActivity.onActivityResult(InspectionActivity.kt:77)
        at android.app.Activity.dispatchActivityResult(Activity.java:7317)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4436)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4484) 
        at android.app.ActivityThread.-wrap19(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1743) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6753) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 

不用担心Failure delivering result。这只是因为此压缩代码是从onActivityResult() 回调调用的,因为要压缩的文件夹路径是作为不同活动的结果传递的。

我该如何解决这个问题?

【问题讨论】:

    标签: android kotlin android-file


    【解决方案1】:

    在循环部分和循环体中调用 fis.read(buffer) 是否可能在您的 while 循环中。在进行 while 检查时尝试设置一个变量。

    while (val data = fis.read(buffer)) {
        zos.write(buffer, 0, data)
    }
    

    【讨论】:

    • 看起来我们无法在 kotlin 的 while 循环内进行赋值。 Android Studio 显示错误。
    • 如何做一个do{} while() 循环,val data = fis.read(buffer) 然后检查它在while 之后是否为空
    • 我确实尝试过。没用。获得相同的 OutOfBounds 异常。
    【解决方案2】:

    典型的 Java 语法是:

    int c;
    while ((c = fid.read(buffer)) >= 0) {
       zos.write(buffer, 0, c);
    }
    

    你不能在 Kotlin 中做同样的事情,因为赋值不是表达式;要在 Kotlin 中做同样的事情,你需要一个带有 ifbreak 的 do/while 循环。

    但几乎没有必要这样做; Kotlin 的标准库有一个扩展函数可以为您处理这个问题:copyTo。如果您使用use 方法,您也不必处理输入流的关闭。这会将您的方法变成:

    for (f in files) {
        Log.d("", "Adding file: " + f.name)
        zos.putNextEntry(ZipEntry(f.name))
        val fis = FileInputStream(f)
        fis.use { fis.copyTo(zos, 2048) }
        zos.closeEntry()
    }
    

    【讨论】:

    • 谢谢。该函数执行时不会崩溃。但是当我打开 zip 文件时,我得到了这个错误,“存档意外结束”
    • 我的猜测是,您遇到了 IO 异常,因为您正在压缩的目录还包含子目录,您无法使用 FileInputStream 打开这些子目录。您可以更改一行以确保您只尝试压缩文件(并且您也应该处理异常)val files = srcFile.listFiles().filter(File::isFile)
    • 实际上,该文件夹包含的只是一些图像。文件夹中没有子目录。
    猜你喜欢
    • 2021-12-25
    • 2015-06-29
    • 1970-01-01
    • 2011-02-02
    • 2011-09-17
    • 1970-01-01
    • 2016-02-05
    • 2021-10-06
    • 2020-06-08
    相关资源
    最近更新 更多