错误:打开失败:ENOENT(没有这样的文件或目录)

Jia*_*ang 30 android

我试图创建一个文件来保存相机中的图片,事实证明我无法创建该文件.但我真的找不到错误.你能看看它并给我一些建议吗?

private File createImageFile(){
        File imageFile=null;
        String stamp=new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File dir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        String imageFileName="JPEG_"+stamp+"_";
        try {
            imageFile=File.createTempFile(imageFileName,".jpg",dir);
        } catch (IOException e) {
            Log.d("YJW",e.getMessage());
        }
        return  imageFile;
    }
Run Code Online (Sandbox Code Playgroud)

我已经添加了许可.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Run Code Online (Sandbox Code Playgroud)

该方法总是会出现这样的错误:

打开失败:ENOENT(没有这样的文件或目录)

Mat*_*son 41

Pictures目录可能尚不存在.它不能保证在那里.

API文档中getExternalStoragePublicDirectory(),代码使用mkdirs以下内容确保目录存在:

File path = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");

try {
    // Make sure the Pictures directory exists.
    path.mkdirs(); 
Run Code Online (Sandbox Code Playgroud)

...所以它可能就像path.mkdirs()在你之前将它添加到现有代码一样简单createTempFile.

  • getExternalStoragePublicDirectory(...) 是 depeceratedString 使用 this.getApplicationContext().getExternalFilesDir(null).toString(); 反而 (2认同)

Bha*_*iya 14

当用户从图库中选择文件时,不能保证所选择的文件是由其他应用程序添加或编辑的。所以,如果用户选择了一个文件,假设它属于另一个应用程序,我们就会遇到权限问题。对此的快速解决方法是在 AndroidManifest.xml 文件中添加以下代码:

<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>
Run Code Online (Sandbox Code Playgroud)

注意:适用于 API 级别 29 或更高

  • 不幸的是,它不适用于 API 级别 30 (2认同)

OBL*_*OBL 9

更换:

Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES)
Run Code Online (Sandbox Code Playgroud)

附:

private File createImageFile() throws IOException {
        // Create an image file name
Run Code Online (Sandbox Code Playgroud)

请务必致电:

mkdirs() // and not mkdir()
Run Code Online (Sandbox Code Playgroud)

这是适合您的代码:

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = new File(Environment.getExternalStorageDirectory().toString(), "whatever_directory_existing_or_not/sub_dir_if_needed/");
        storageDir.mkdirs(); // make sure you call mkdirs() and not mkdir()
        File image = File.createTempFile(
                imageFileName,  // prefix
                ".jpg",         // suffix
                storageDir      // directory
        );

        // Save a file: path for use with ACTION_VIEW intents

        mCurrentPhotoPath = "file:" + image.getAbsolutePath();
        Log.e("our file", image.toString());
        return image;
    }
Run Code Online (Sandbox Code Playgroud)

根据Android Studio文档中给出的示例我遇到了不好的经历,我发现在stackoverflow中有很多其他人对此特定主题有相同的看法,这是因为即使我们设置了

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Run Code Online (Sandbox Code Playgroud)

某些设备问题仍然存在.

我的经验是,当我在调试模式下尝试它时,该示例有效,经过3次测试后,我的SD突然被破坏了,但我不认为这与他们的例子有关(很有趣).我买了一张新的SD卡并再次尝试,只是意识到发布和调试模式仍然执行相同的错误日志:目录不存在ENOENT.最后,我不得不自己创建目录,其中包含从手机相机中捕获的图片.而我是对的,它的工作非常完美.

我希望这可以帮助你和其他人在那里寻找答案.


per*_*ser 5

我将 contentResolver 与 URI 一起使用,它对我有用。在另一篇SO帖子中看到它,但我找不到。

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) {
        result = contentURI.getPath();
    } else {
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你....


小智 5

对此的快速解决方法是在 AndroidManifest.xml 文件中添加以下代码:

<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>
Run Code Online (Sandbox Code Playgroud)

注意:适用于 API 级别 29 或更高

  • 这是 API 29 的临时解决方案,它不适用于 API 30 (2认同)