解压缩时,FileOutputStream会抛出FileNotFoundException

时间:2011-09-08 20:11:17

标签: java android file

我正在使用通过谷歌找到的类来解压缩.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;
  }

下载.zip的另一个AsyncTask

@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

7 个答案:

答案 0 :(得分:14)

如果涉及的目录不存在,

FileOutputStream将抛出FileNotFoundException。我在这里看不到任何目录创建代码,甚至没有任何代码可以检查Path是否存在,所以这可能是正在发生的事情。

答案 1 :(得分:8)

我再次使用(是目录)消息错误获取FileNotFoundException。

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

尝试使用

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

然后

File file = new File(directory, FileName);

而不是你的代码。

答案 2 :(得分:2)

您的第一个版本依赖于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();

其余的事情无论如何都会发生。

答案 3 :(得分:0)

来自FileOutputStream构造函数的javadoc

  

抛出:
  FileNotFoundException - 如果文件存在但是是目录   而不是常规文件,不存在但无法创建,或   由于任何其他原因无法打开

通常,如果您没有创建文件的权限或者文件系统的一部分是只读的,则会发生FileNotFoundException(虽然我不确定这在Android中适用的程度)

答案 4 :(得分:0)

此处的问题是由于嵌套在给定zip中的zip文件或目录引起的。如果给定的ZipEntry是一个目录,则需要创建目录并使用FileOutputStream跳过写入。

使用Support Library检查给定的zipEntry是否是目录并使用zipEnrty.isDirectory()创建目录,然后继续使用下一个zipEntry而不使用fileOutputStream编写它。

以下是解压缩zip文件的完整代码:

zipEntry.mkDirs()

答案 5 :(得分:-1)

我曾经使用以下代码从app小部件写入内部和外部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();

答案 6 :(得分:-2)

从Manifest中删除“android:maxSdkVersion =”18“”

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

您在Manifest文件中声明。

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