开发者

FileOutputStream throws FileNotFoundException when UnZipping

I'm using a class that I found through google to unzip a .zip file.. The .zip contains files and folder. The problem is that FileOutputStream throws FileNotFoundException.. But the file should be taken from the .zip file so how can it previously exist?

Here is the code I'm using in the 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;
  }

Another AsyncTask which downloads the .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())
              {
      开发者_StackOverflow社区            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;
      }

I get again the FileNotFoundExcpetion with (is a directory) message error!.


FileOutputStream will throw FileNotFoundException if the directory(s) involved don't exist. I don't see any directory-creation code here, or even any code to check if Path exists, so that's probably what's going on.


I get the FileNotFoundException again with (is a directory) message error.

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

Try using

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

and then

File file = new File(directory, FileName);

instead of your code.


Your first version relies on dirChecker() which you haven't posted, but either it doesn't work correctly, or your ZIP file doesn't contain directory entries at all, which is prefectly legal, so you shouldn't rely on them being present anyway.

Your second version is better but you don't need all this:

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

You just need this:

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

The rest will happen anyway.


The problem here is caused due to zip files or directories nested within the given zip. In case the given ZipEntry is a directory, you need to create the directory and skip writing with the FileOutputStream.

use zipEnrty.isDirectory() to check whether the given zipEntry is a directory and create the directory using zipEntry.mkDirs() and proceed to the next zipEntry without writing it using fileOutputStream.

Here is the full code for unzipping a zip file :

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();
        }
    }
}


From the javadocs for the FileOutputStream constructor

Throws:
FileNotFoundException - if the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason

Often, a FileNotFoundException occurs if you do not have permissions to create files or that part of the file system is read-only (though I'm not sure to what extent this applies in Android)


I used to write from app widget to both internal and external Android memory with following code:

        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();

Where path was both:

        path = mContext.getFilesDir();

or

        path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);

and

        path.mkdirs(); 

In both cases I've got a FileNotFoundException and a created file with zero length.

I've managed to write to both types of Android memory with a following function:

   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;
}

And following usage:

          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();


Remove the "android:maxSdkVersion="18" " from Manifest

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

You declared in Manifest file.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜