【问题标题】:FileOutputStream throws FileNotFoundException when UnZipping解压时 FileOutputStream 抛出 FileNotFoundException
【发布时间】:2011-09-08 20:11:17
【问题描述】:

我正在使用通过 google 找到的类来解压缩 .zip 文件。.zip 包含文件和文件夹。问题是FileOutputStreamthrowsFileNotFoundException..但是该文件应该从.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!。

【问题讨论】:

  • Path的内容是什么?会不会是缺少尾随/

标签: java android file


【解决方案1】:

如果涉及的目录不存在,FileOutputStream 将抛出 FileNotFoundException。我在这里看不到任何目录创建代码,甚至没有任何代码来检查Path 是否存在,所以这可能就是发生了什么。

【讨论】:

  • 但是文件+文件夹是从.zip文件中提取出来的。.zip中有很多文件,所以我应该在提取之前手动创建所有文件!!我检查目录(dirChecker)..
【解决方案2】:

我再次收到 FileNotFoundException 并出现(是一个目录)消息错误。

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

尝试使用

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

然后

File file = new File(directory, FileName);

而不是你的代码。

【讨论】:

  • 您能告诉我为什么这不能提供问题的答案吗?根据stackoverflow.com/help/how-to-answer ,我认为我的回答也可以解决问题,除非为时已晚:)
  • 这是一个不错的答案。如果您查看我留言时的时间戳,那是在您第一次发布此答案之后。那个版本的格式很差,没有方向性。
  • @jvperrin 最初的编辑工作做得很好。我建议您研究他和 JonathanLeffler 对您的答案所做的更改,并对其进行改进;)
  • 是的,很抱歉我的基本降价用法很差。 增强:)
【解决方案3】:

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

其余的都会发生。

【讨论】:

    【解决方案4】:

    这里的问题是由于嵌套在给定 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();
            }
        }
    }
    

    【讨论】:

    • 完美答案!
    【解决方案5】:

    来自 FileOutputStream 构造函数的 javadocs

    投掷:
    FileNotFoundException - 如果文件存在但是是一个目录 而不是常规文件,不存在但无法创建,或者 其他原因打不开

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

    【讨论】:

    • 我正在尝试写入外部 sd 并且我有使用权限 (Write_External_Sd..) 所以我可以在那里写入
    【解决方案6】:

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

    【讨论】:

    • 与它无关。问题是关于 ZIP 文件的。
    【解决方案7】:

    从 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"
        />
    

    【讨论】:

    • 即使他有,证据为零,您也需要解释为什么这会解决问题,但事实并非如此。
    • 我在 sd 卡中下载图像和视频时遇到了同样的问题。所以我只是从清单中删除 android:maxSdkVersion="18" 。它工作正常。
    猜你喜欢
    • 1970-01-01
    • 2013-12-08
    • 2019-09-17
    • 2016-04-05
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 2015-11-06
    相关资源
    最近更新 更多