Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading ZipFile with android DocumentFile

I want to read a zip file with java.util.zip.ZipFile with android DocumentFile

Illustration:

With Storage Access Framework, I get the uri of a file in the android system and create a Documentfile with it. The document file is a folder that has a zip file "data.zip"

Data.zip has over 80 entries consisting of both text files and media file( >= 8mb <= 20mb). So, zip file is over 932mb.

With the filePAth, I can read an entry directly with the snippet below :

zipFile = new ZipFile(zipPath);
                ZipEntry zipEntry = zipFile.getEntry(name);
                if (zipEntry != null) {
                    return writeByteArraysToFile(ByteStreams.toByteArray(zipFile.getInputStream(zipEntry)), ext);
                }

This works great on devices that does not required Storage access Framework.

For Devices that uses SAF, I am using a DocumentFile and I have reading the content like this :

InputStream inputStream = context.getContentResolver().openInputStream(documentFile.getUri());

                BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
                ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);
                ZipEntry entry;
                while ((entry = zipInputStream.getNextEntry()) != null) {

                    Log.e("field", entry.getName());
                    if (entry.getName().contains(name)) {
                        File file = PBUtils.writeByteArraysToFile(ByteStreams.toByteArray(zipInputStream), ext);
                        zipInputStream.closeEntry();
                        inputStream.close();
                        zipInputStream.close();
                        bufferedInputStream.close();
                        return file;
                    }
                    zipInputStream.closeEntry();
                }
                inputStream.close();

Not This Works, But here's the problem:

  1. while iterating through the entries to find a particular entry, it is slow. I debug and find out the time it take to read a media entry causes the delay.

I need solutions on how I can make this faster and need to know if there's any way I can use ZipFile with DocumentFile so I can at least do something like this:

zipFile = new ZipFile(documentFileUri);
                ZipEntry zipEntry = zipFile.getEntry(name);
                if (zipEntry != null) {
                    return writeByteArraysToFile(ByteStreams.toByteArray(zipFile.getInputStream(zipEntry)), ext);
                }
like image 751
Nosakhare Belvi Avatar asked Mar 26 '17 07:03

Nosakhare Belvi


2 Answers

It's really a bummer - Google is force-feeding us unwanted Scope Storage, but not providing means to work with it where needed. One way to do this:

    // mDocFile is a DocumentFile..., you also need a context (activity, service, app...
    String getDocReadableFilePath(DocumentFile mDocFile, Context context) {
        if (mDocFile != null && mDocFile.isFile()) {
            try {
                ParcelFileDescriptor parcelFileDescriptor =
                        context.getContentResolver().openFileDescriptor(mUri, "r"); // gets FileNotFoundException here, if file we used to have was deleted
                if (parcelFileDescriptor != null) {
                    int fd = parcelFileDescriptor.detachFd(); // if we want to close in native code
                    return "/proc/self/fd/" + fd;
                }
            }
            catch (FileNotFoundException fne) {
                return "";
            }
        }
    }

    // Now you may use:
    String documentFilePath = getDocReadableFilePath(docFile, context);
    ZipFile zf = new ZipFile(documentFilePath);
like image 125
gregko Avatar answered Sep 29 '22 04:09

gregko


With android DocumentFile you have to use java.util.zip.ZipInputStream or java.util.zip.ZipOutputStream instead of java.util.zip.ZipFile that can be used with android context.getContentResolver().openOutputStream() and context.getContentResolver().openInputStream()

like image 33
k3b Avatar answered Sep 29 '22 06:09

k3b