как читать из zip-файла в папке, выбранной намерением ACTION_OPEN_DOCUMENT_TREE?

как читать из zip-файла в папке, выбранной намерением ACTION_OPEN_DOCUMENT_TREE?

Мое приложение позволяет пользователю выбирать папку с помощью намерения ACTION_OPEN_DOCUMENT_TREE. В этой папке у меня будет Zipfile с определенным именем. Цель состоит в том, чтобы прочитать этот Zipfile с помощью java.util.zip.ZipFile.

Как создать экземпляр ZipFile с этим конкретным именем Zipfilename из предоставленного URI (Folderinfo) в onActivityResult?

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Uri treeUri = data.getData();
    String sPath=treeUri.getPath();

    java.util.zip.ZipFile myzip=new java.util.zip.ZipFile("mypath"); <-- Constructor expects File or Path as String. Howto handle this with the Uri ?

person mcfly soft    schedule 20.04.2015    source источник


Ответы (2)


Как создать экземпляр ZipFile с этим конкретным именем Zipfilename из предоставленного URI (Folderinfo) в onActivityResult?

Нельзя, так как файла нет, а ZipFile нужен файл. Вы можете получить только InputStream, используя openInputStream() для ContentResolver, и только если вы получите Uri для того конкретного файла, который ищете.

Ваши варианты выглядят следующим образом:

  • Используйте ZipInputStream, который может обернуть InputStream

  • Найдите какую-нибудь стороннюю библиотеку, которая принимает InputStream в качестве входных данных и предоставляет вам лучший API.

  • Скопируйте файл ZIP в часть внутренней памяти вашего приложения и прочитайте его содержимое, используя ZipFile

person CommonsWare    schedule 20.04.2015
comment
Как я писал. У меня уже будет zip-файл в той папке, которую выбирает пользователь. Так действительно ли нет возможности создать ZipFile в этом уже существующем файле на основе Folder-URI? - person mcfly soft; 20.04.2015
comment
@ user1344545: Как я написал, файла нет. ACTION_OPEN_DOCUMENT_TREE не возвращает Folder-URI. Он возвращает Uri тому, что хочет DocumentProvider. Нет необходимости, чтобы он сопоставлялся с каким-либо каталогом на самом устройстве. Uri, который возвращает DocumentProvider для определенного документа, не должен сопоставляться с каким-либо файлом на самом устройстве. Например, DocumentProvider может поддерживаться облаком, а не локальными файлами, или файлы могут находиться на съемных носителях, к которым у провайдера есть доступ, а у вас нет. - person CommonsWare; 20.04.2015
comment
Если я вручную перемещаю zip-файл myzip.zip в папку /sdcard/myfolder/ с помощью проводника (это то, что я имею в виду, когда файл уже есть). Затем я запускаю приложение и выбираю папку /sdcard/myfolder с намерением ACTION_OPEN_DOCUMENT_TREE и вижу файл myzip.zip . Затем я ожидаю, что файл есть, и я надеюсь, что смогу перечислить его с помощью API. Поэтому я надеялся прочитать и этот файл. Но спасибо, попробую с ZipInputStream - person mcfly soft; 20.04.2015
comment
@ user1344545 - нет, ваши ожидания неверны. Не обязательно какой-либо фактический файл, и даже если он есть, в зависимости от местоположения он может быть доступен только для некоторого внутреннего демона Android, а не непосредственно для вашего приложения. Метод ZipInputStream — это то, как вы предполагаете сделать это, поскольку он использует тот факт, что, хотя многие из этих абстракций не будут предоставлять вам реальный файл, они предоставят вам InputStream проксируется через любую реализацию, которая на самом деле находится за кулисами. - person Chris Stratton; 21.04.2015
comment
Спасибо, Крис. Я уже реализовал решение ZipInputStream, предложенное CommonsWare. Я также принял. - person mcfly soft; 21.04.2015

Я работал над этой проблемой и в итоге выбрал стратегию @CommonsWare, упомянутую как третий вариант, который копирует файл в место, отличное от SD-карты, и загружает его как ZipFile. Это работает хорошо, поэтому я делюсь своим фрагментом для всех.

 public static ZipFile loadCachedZipFromUri(Context context, Uri uri, String filename){
    File file = new File(context.getCacheDir(), filename);
    String fileName = context.getCacheDir().getAbsolutePath() + '/' + filename;
    ZipFile zip = null;

    if (file.exists()){
        Log.d(TAG, "file exists");
        try {
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // N for Nougat
                zip = new ZipFile(fileName, Charset.forName("ISO-8859-1"));

            }else{
                zip = new ZipFile(fileName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return zip;
    }

    DocumentFile dest = DocumentFile.fromFile(file);

    InputStream in = null;
    OutputStream out = null;

    Log.d(TAG, "Copy started");
    try {
        in = context.getContentResolver().openInputStream(uri);
        out = context.getContentResolver().openOutputStream(dest.getUri());
        byte[] buf = new byte[2048];
        int len = 0;
        while((len = in.read(buf)) >= 0){
            out.write(buf, 0, len);
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            in.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    Log.d(TAG, "Load copied file");
    try {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // N for Nougat
            zip = new ZipFile(fileName, Charset.forName("ISO-8859-1"));

        }else{
            zip = new ZipFile(fileName);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return zip;
}
person Naofumi    schedule 14.06.2017