FileOutputStream генерирует FileNotFoundException при разархивировании - PullRequest
6 голосов
/ 09 сентября 2011

Я использую класс, который я нашел через google, чтобы распаковать файл .zip. .Zip содержит файлы и папку. Проблема в том, что FileOutputStream throws FileNotFoundException .. Но файл должен быть взят из файла .zip, так как он может существовать ранее?
Вот код, который я использую в AsyncTask:

@Override
protected Boolean doInBackground(String... params) {
    try {

        String zipFile = Path + FileName;

        FileInputStream fin = new FileInputStream(zipFile);
        ZipInputStream zin = new ZipInputStream(fin);
        ZipEntry ze = null;
        while ((ze = zin.getNextEntry()) != null) {

            if (ze.isDirectory()) {
                dirChecker(ze.getName());
            } else {
                FileOutputStream fout = new FileOutputStream(Path
                        + ze.getName()); // <-- crashes here
                while ((length = zin.read(buffer)) > 0) {
                    fout.write(buffer, 0, length);
                    publishProgress(length);

                }

                zin.closeEntry();
                fout.close();
            }

        }
        zin.close();
    } catch (Exception e) {
        mProgressDialog.dismiss();
        return false;
    }

    return true;
  }

Другой AsyncTask, который загружает .zip:

@Override
protected Boolean doInBackground(String... params) {
      try {
          URL url = new URL(params[0]);
          URLConnection conexion = url.openConnection();

          conexion.connect();

          int lenghtOfFile = conexion.getContentLength();
          File f = new File(Path+FileName);
          if(!f.exists())
          {
              f.mkdirs();
              if(!f.createNewFile())
              {
                  f.delete();
                  f.createNewFile();
              }
          }

          InputStream input = new BufferedInputStream(url.openStream());
          OutputStream output = new FileOutputStream(Path+FileName);

          byte data[] = new byte[1024];

          long total = 0;

          while ((count = input.read(data)) != -1) {
              total += count;
              publishProgress((int)((total*100)/lenghtOfFile));
              output.write(data, 0, count);
          }

          output.flush();
          output.close();
          input.close();
          return true;
      } catch (Exception e)     
      {
        e.printStackTrace();
        e.getCause();
        return false;
      }

Я снова получаю сообщение об ошибке FileNotFoundExcpetion with (is directory)!.

Ответы [ 7 ]

14 голосов
/ 09 сентября 2011

FileOutputStream выдаст FileNotFoundException, если соответствующие каталоги не существуют. Я не вижу здесь никакого кода создания каталога или даже кода, который бы проверял, существует ли Path, так что, вероятно, это и происходит.

8 голосов
/ 04 декабря 2013

Я снова получаю FileNotFoundException с сообщением об ошибке (является каталогом).

File f = new File(Path+FileName);
f.mkdirs();

Попробуйте использовать

File directory = new File(Path);
directory.mkdirs();

и затем

File file = new File(directory, FileName);

вместотвой код.

2 голосов
/ 09 сентября 2011

Ваша первая версия опирается на dirChecker(), которую вы не опубликовали, но либо она не работает должным образом, либо ваш ZIP-файл вообще не содержит записей каталога, что совершенно законно, поэтому вам не следуетв любом случае не полагайтесь на их присутствие.

Ваша вторая версия лучше, но вам все это не нужно:

 File f = new File(Path+FileName);
          if(!f.exists())
          {
              f.mkdirs();
              if(!f.createNewFile())
              {
                  f.delete();
                  f.createNewFile();
              }
          }

Вам просто нужно это:

File f = new File(Path, FileName);
f.getParentFile().mkdirs();

Остальное все равно случится.

0 голосов
/ 26 августа 2017

Удалите "android: maxSdkVersion =" 18 "" из манифеста

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
   android:maxSdkVersion="18"/>

Вы объявлены в файле манифеста.

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    />
0 голосов
/ 22 ноября 2016

Проблема здесь вызвана тем, что zip-файлы или каталоги вложены в данный zip-архив.Если данный ZipEntry является каталогом, вам нужно создать каталог и пропустить запись с помощью FileOutputStream.

используйте zipEnrty.isDirectory(), чтобы проверить, является ли данный zipEntry каталогом, и создайте каталог с помощью zipEntry.mkDirs()перейдите к следующему zipEntry, не записывая его с помощью fileOutputStream.

Вот полный код для распаковки zip-файла:

import java.io.*;
import java.util.zip.*;

public class Unzip
{
    public static void main (String args[])
    {
        try
        {
            final int BUFFER = 1024;
            int count;
            byte data[] = new byte[BUFFER];
            String path="res/Example.zip";

            BufferedOutputStream bufferedOutputStream = null;
            FileInputStream fileInputStream = new FileInputStream(path);
            ZipInputStream zipInputStream = new ZipInputStream(new  BufferedInputStream(fileInputStream));
            ZipEntry zipEntry;

            while((zipEntry = zipInputStream.getNextEntry()) != null)
            {
                System.out.println("Extracting: " +zipEntry);
                File file=new File(zipEntry.getName());
                if(zipEntry.isDirectory())
                {
                    file.mkdirs();
                    continue;
                }
                FileOutputStream fileOutputStream = new     FileOutputStream(file,false);
                bufferedOutputStream = new BufferedOutputStream(fileOutputStream, BUFFER);

                while ((count = zipInputStream.read(data, 0, BUFFER))!= -1)
                bufferedOutputStream.write(data, 0, count);

                bufferedOutputStream.flush();
                bufferedOutputStream.close();
            }
            zipInputStream.close();
        } 
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}
0 голосов
/ 09 марта 2013

Я писал из виджета приложения во внутреннюю и внешнюю память Android со следующим кодом:

        URL adr = new URL(cleanUrl);


        HttpURLConnection urlConnection = (HttpURLConnection) adr.openConnection();

        urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);
        urlConnection.setReadTimeout(5000);

        urlConnection.connect();

        File file = new File(path, name);

        FileOutputStream fileOutput = new FileOutputStream(file);

        InputStream inputStream = urlConnection.getInputStream();

        byte[] buffer = new byte[1024];
        int bufferLength = 0; 
        while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
            fileOutput.write(buffer, 0, bufferLength);
        }
        fileOutput.flush();

        fileOutput.close();

Где путь был и:

        path = mContext.getFilesDir();

или

        path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);

и

        path.mkdirs(); 

В обоих случаях у меня есть FileNotFoundException и создан файл нулевой длины.

Мне удалось записать в оба типа памяти Android с помощью следующей функции:

   protected InputStream get(String url) throws ClientProtocolException, IOException {

    final HttpClient client = new DefaultHttpClient();

    HttpGet getRequest = new HttpGet(url);

    HttpResponse response = client.execute(getRequest);
    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
        return null;
    }


    final HttpEntity entity = response.getEntity();
    if (entity != null) {
        try {
            return entity.getContent();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    return null;
}

и следующего использования:

          File file = new File(path, name);

        FileOutputStream fileOutput = new FileOutputStream(file);
        InputStream inputStream = get(cleanUrl);            

        byte[] buffer = new byte[1024];
        int bufferLength = 0;
        while ( (bufferLength = inputStream.read(buffer)) > 0 ) {

            fileOutput.write(buffer, 0, bufferLength);
        }
        fileOutput.flush();

        fileOutput.close();
0 голосов
/ 09 сентября 2011

Из javadoc для конструктора FileOutputStream

Выдает:
FileNotFoundException - если файл существует, но является каталогом вместо обычного файла, не существует, но не может быть создан, или не может быть открыт по любой другой причине

Часто возникает исключение FileNotFoundException, если у вас нет прав на создание файлов или эта часть файловой системы доступна только для чтения (хотя я не уверен, в какой степени это применимо в Android)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...