为什么有时抛出FileNotFoundException

该代码大部分时间工作,但有一段时间抛出exception。 无法弄清楚是什么原因造成的。

什么是在创build一个文件

/storage/emulated/0/Download/theFileName.jpg

并写入数据(从源文件存在),但得到“文件不存在”例外新创build的文件。

(它具有uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE", and uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE在清单中uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE", and uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE ”)。

 File sourceFile = new File(theSourceFileFullPath); if (sourceFile.exists()) { File downloadDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); String downloadPath = downloadDirectory.getPath(); String newFilePath = (downloadPath + "/" + fileName); File newFile = new File(newFilePath); try { FileInputStream in = new FileInputStream(sourceFile); // ava.io.FileNotFoundException: // /storage/emulated/0/Download/theFileName.jpg: open failed: ENOENT (No such file or directory) // exception at this line FileOutputStream out = new FileOutputStream(newFile); //...... } catch (Exception e) {} } 

Solutions Collecting From Web of "为什么有时抛出FileNotFoundException"

我可以考虑以下可能的原因:

  1. 无法创build新文件,因为SD卡上没有可用空间。 下次遇到此问题时,请尝试通过文件pipe理器或“设置” – >“存储”来查看是否至less有一些可用空间。 如果这是用户设备上发生的情况,我怀疑你可以做些什么。
  2. SD卡由于某些操作系统故障或物理上未连接而不可用,因此无法创build文件。 再次 – 没有什么可以做的,除了显示一些Toast与错误消息。
  3. 如何生成文件path的fileName部分? 有时文件不能被创build,因为文件名包含(特定的设备)不支持的字符。 例如我有HTC Desire X And​​roid 4.1.2,如果文件名包含冒号,则无法创build类似于您的代码的文件。 尝试另一种方式来生成文件名,看看是否有所作为。
  4. 在创build文件之前,你确定Downloads目录是否存在? 写下如下内容:

     if (!downloadDirectory.exists()) { downloadDirectory.mkdirs(); } 
  5. WRITE_EXTERNAL_STORAGE权限在Android 6上被认为是危险的,因此用户可以随时撤销。 确保在写入文件之前用户没有撤​​销此权限。
  6. 处理完它后,请始终closuresI / Ostream 。 将finally子句添加到try-catch块中,并closures其中的in outstream:

     finally { if (in != null) { try { in.close(); } catch (Exception e) { } } if (out != null) { try { out.close(); } catch (Exception e) { } } } 
  7. 最后一个 – 最后我没有select。 :)我想这个问题也可能出现,如果你从多个线程写入相同的文件 。 如果是这种情况,请尝试同步对文件写入代码的访问。

根据Java文档 – 类FileNotFoundException :

public class FileNotFoundException extends IOException

表示尝试打开由指定的path名​​表示的文件失败。

当具有指定pathname的文件不存在时, FileInputStreamFileOutputStreamRandomAccessFile构造函数将引发此exception。 如果文件存在但由于某种原因无法访问,例如当试图打开只读文件进行写入时,也会由这些构造函数抛出。

要恢复,有三种情况可能会引发FileNotFoundException

  1. 指定的文件不存在。
  2. 指定的文件实际上是一个目录。
  3. 指定的文件由于某种原因无法打开阅读。

新创build的文件有“文件不存在”exception。

在你的代码中,我没有看到两件事

  1. 成功写入后删除文件。 我根本不是在开玩笑。 如果我有这样一个类,那个错误,我会做一种testing,这将完成从源文件复制内容后删除downlaodDirectory 。 在这种情况下,它会通过该方法,否则你会得到另一个,但更具体的错误 – 就像我的话: 无法删除文件。 在使用它
  2. 写入数据后closures文件。 我也没有看到closures文件的方法。 在你的代码中,似乎是你的文件仍然是打开的,所以你再次运行一个应用程序,你会得到这个不可预知的错误。

要解决这个问题,只需在使用file.close()方法处理数据之后closures这两个文件file.close()

希望它有帮助

  1. 由于您创build文件的方式可能会发生此问题:

     String downloadPath = downloadDirectory.getPath(); String newFilePath = (downloadPath + "/" + fileName); File newFile = new File(newFilePath); 

    危险的代码在这里:

     String newFilePath = (downloadPath + "/" + fileName); 

    相反,尝试使用以下方法:

     File newFile = new File(downloadDirectory, fileName); 
  2. SD卡可用性 – 请查看以下文档http://developer.android.com/training/basics/data-storage/files.html#WriteExternalStorage 。 这可能是因为媒体没有安装(例如,在用户通过USB将设备连接到计算机时发生的旧设备上)因此,请尝试检查是否安装了媒体:

     /* Checks if external storage is available for read and write */ public boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { return true; } return false; } 

    如果没有通知用户。

你没有发布完整的exception堆栈跟踪,但我发现确切的问题由SO解决。

 java.io.FileNotFoundException: /storage/emulated/0/bimagechooser/1429031333305.jpg: open failed: ENOENT (No such file or directory) 

使用这个库图像select器库。 并需要重新分解代码。

这个家伙coomar2841 。 一定会帮助你 因为他花了几个小时解决问题。 所以节省你的时间。

采取了com.kbeanie.imagechooser的来源,并将其放到您的APP,删除该库的gradle声明,APP应该工作。

请查看 GitHub问题

我希望它能为你工作。 🙂

我希望你的代码在文件中写入数据是完美的我只是集中在你的问题。我认为有两种可能性,以获得文件没有发现exception。

  1. 有些时候文件名不支持一些特殊字符当你提供这种字符给文件名称在那个时候文件是不正确的生成这就是为什么这个错误发生所以请确保您的文件名是适当的。
  2. 其次是你的文件扩展名。在这里你没有指定你有哪种types的文件。

在这里我有一些代码片段,我希望这会帮助你解决问题。

  File file=new File(Environment.getExternalStorageDirectory()+"/"+ConstansClass.FOLDERNAME); if(!file.exists()) { file.mkdir(); } String file=filename.replaceAll("[^a-zA-Z0-9.-]", " "); yourDir = new File(file, file+".mp3"); if(yourDir.exists()) { return yourDir; } 

编辑

我很抱歉lannf我不知道你的代码究竟发生了什么,但我有一个代码片断,这是从soundcloude下载mp3文件和存储在我的本地storage.i认为这是完全相同的要求。因此,我有我的职位下面的代码。

  @Override protected File doInBackground(Void... params) { //File sdCardRoot = Environment.getExternalStorageDirectory()+"/Music"; File file=new File(Environment.getExternalStorageDirectory()+"/"+ConstansClass.FOLDERNAME); if(!file.exists()) { file.mkdir(); } String filename=soundCloudeResponse.getTitle();//.replaceAll("[^a-zA-Z0-9.-]", " "); yourDir = new File(file, filename+".mp3"); if(yourDir.exists()) { return yourDir; } String url=soundCloudeResponse.getStream_url()+"?"+ConstansClass.SOUNDCLOUDE_CLIENT_ID; URL u = null; try { DebugLog.e("Request Url"+ url); u = new URL(url); URLConnection conn = u.openConnection(); int contentLength = conn.getContentLength(); DataInputStream stream = new DataInputStream(u.openStream()); byte[] buffer = new byte[contentLength]; stream.readFully(buffer); stream.close(); DataOutputStream fos = new DataOutputStream(new FileOutputStream(yourDir)); fos.write(buffer); fos.flush(); fos.close(); DebugLog.d("Download Complete in On Background"); } catch (MalformedURLException e) { sucess=false; e.printStackTrace(); } catch (IOException e) { sucess=false; e.printStackTrace(); } catch (Exception e) { sucess=false; e.printStackTrace(); DebugLog.e("Error ::"+e.getMessage()); } return yourDir; } 

我认为你是聪明的开发者,所以你可以根据你的要求修改这个代码。

好运