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

как да чета от zip файл в папка, която е избрана от ACTION_OPEN_DOCUMENT_TREE Intent?

Моето приложение позволява на потребителя да избере папка чрез намерението 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, спомената като третата опция, която е копиране на файл на място, различно от sdcard, и зареждане като 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