Исключение IndexOutOfBounds при попытке преобразовать содержимое папки в zip-файл - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть требование, когда у меня есть две папки, и каждая из них должна быть преобразована в соответствующие им 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() обратного вызова, поскольку путь к папке, подлежащей сжатию, передается в результате другой операции.

Как я могу исправить эту проблему?

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Типичный синтаксис Java для этого:

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

Вы не можете сделать то же самое в Kotlin, потому что назначение не является выражением;чтобы сделать то же самое в Kotlin, вам нужен цикл do / while с if и break.

Но в этом нет особой необходимости;Стандартная библиотека 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()
}
0 голосов
/ 13 сентября 2018

Может быть, в вашем цикле while вы вызываете fis.read (буфер) в части цикла и в теле цикла. Попробуйте установить переменную, когда выполняете проверку while.

while (val data = fis.read(buffer)) {
    zos.write(buffer, 0, data)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...