Error: open failed: ENOENT (No such file or directory)
Asked Answered
C

12

80

I was trying to create a file to save pictures from the camera, it turns out that I can't create the file. But I really can't find the mistake. Can you have a look at it and give me some advice?

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

And I have added the permission.

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

The method always gives such mistakes:

open failed: ENOENT (No such file or directory)

Cocaine answered 18/3, 2016 at 15:46 Comment(5)
The example given in the API reference has this line: // Make sure the Pictures directory exists. path.mkdirs();. Are you sure the directory already exists?Manly
Try this link: android canvas save always java.io.IOException: open failed: ENOENTCharin
Thanks! In the training there isn't such a hint. I should have searched the API references. Thanks!Cocaine
@JiaweiYang Was it my suggestion that worked? If so, I'll add it as an answer.Manly
Because Android 10 (Api level 29) and higher doesnt allow to create a folder in external storage directly.. You should use getExternalFilesDir(Environment.DIRECTORY_PICTURES)Denunciatory
M
74

The Pictures directory might not exist yet. It's not guaranteed to be there.

In the API documentation for getExternalStoragePublicDirectory(), the code ensures the directory exists using mkdirs:

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

try {
    // Make sure the Pictures directory exists.
    path.mkdirs(); 

...so it may be as simple as adding that path.mkdirs() to your existing code before you createTempFile.

Manly answered 18/3, 2016 at 15:58 Comment(2)
required to check the new directory has been created or not by if (!path.mkdirs()) { Log.d("Un Available:" , path.getAbsolutePath()); }Domestic
getExternalStoragePublicDirectory(...) is depecratedString use this.getApplicationContext().getExternalFilesDir(null).toString(); insteadBi
D
20

when a user picks a file from the gallery, there is no guarantee that the file that was picked was added or edited by some other app. So, if the user picks on a file that let’s say belongs to another app we would run into the permission issues. A quick fix for that is to add this code in the AndroidManifest.xml file:

<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Note: For Android 11 refer Scope storage Enforcement Policy https://developer.android.com/about/versions/11/privacy/storage

Dull answered 15/7, 2020 at 9:44 Comment(3)
It not works with API level 30, unfortunatelyDeathblow
Android 11 the system ignores the requestLegacyExternalStorage flag, Scope Storage Android 11 android:preserveLegacyExternalStorage="true" to Data Merge/Move. for more detail about scope storage please refer Link: developer.android.com/about/versions/11/privacy/storage and developer.android.com/training/data-storage#scoped-storageDull
android:preserveLegacyExternalStorage="true" required for your existing APP when user update his/her android OS to 11. with this you can transfer data from your old DIR to New DIR W.R.T 11 Scope Storage Policy.Dull
K
13

Replace:

Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES)

With:

private File createImageFile() throws IOException {
        // Create an image file name

make sure you call:

mkdirs() // and not mkdir()

Here's the code that should work for you:

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

I had a bad experience following the example given in Android Studio Documentation and I found out that there are many others experiencing the same about this particular topic here in stackoverflow, that is because even if we set

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

the problem persists in some devices.

My experience was that the example worked when I tried it in debug mode, after that 3 more tests it so happened that my SD suddenly was corrupted, but I don't think it has to do with their example (funny). I bought a new SD card and tried it again, only to realize that still both release and debug mode did the same error log: directory does not exist ENOENT. Finally, I had to create the directories myself whick will contain the captured pictures from my phone's camera. And I was right, it works just perfect.

I hope this helps you and others out there searching for answers.

Kassel answered 7/12, 2016 at 3:17 Comment(1)
It is not working for android 11Mertens
S
9

A quick fix for that is to add this code in the AndroidManifest.xml file:

<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Note: Applicable for API level 29 or Higher

Sanjuana answered 22/10, 2020 at 3:2 Comment(1)
this is a teporary sulution for API 29 only it will not work with API 30Beaverboard
S
5

I used the contentResolver with the URI and it worked for me. Saw it in another SO post which i can't find.

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

hope it helps....

Shorthorn answered 14/12, 2016 at 17:7 Comment(0)
S
2

I have solved like this:

        public Intent getImageCaptureIntent(File mFile) {
             Intent mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
             Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", mFile);
             mIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);

             // The tip is this code below
             List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(mIntent, PackageManager.MATCH_DEFAULT_ONLY);
                 for (ResolveInfo resolveInfo : resInfoList) {
                      String packageName = resolveInfo.activityInfo.packageName;
                      grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 }

             return  mIntent;
        }
Scansorial answered 22/6, 2017 at 20:13 Comment(0)
R
1

If you are using kotlin then use below function. you have to provide a path for storing image, a Bitmap (in this case a image) and if you want to decrease the quality of the image then provide %age i.e 50%.

fun cacheLocally(localPath: String, bitmap: Bitmap, quality: Int = 100) {
        val file = File(localPath)
        file.createNewFile()
        val ostream = FileOutputStream(file)
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, ostream)
        ostream.flush()
        ostream.close()
    }

hope it will work.

Repulsive answered 30/7, 2019 at 5:44 Comment(1)
kotlin or not does not matter here.Casiano
S
1
File dirPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File imageFile = new File(dirPath, "YourPicture.jpg");

try {
    if(!dirPath.isDirectory()) {
       dirPath.mkdirs(); 
    } 
    imageFile.createNewFile();

} catch(Exception e) {
    e.printStackTrace();
}
Sapper answered 13/4, 2020 at 16:43 Comment(0)
N
0

Try this:

private File createImageFile() throws IOException {  

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());  

    String imageFileName="JPEG_"+stamp+".jpg";  

    File photo = new File(Environment.getExternalStorageDirectory(),  imageFileName);  

    return photo;
}  
Nucleo answered 18/3, 2016 at 15:54 Comment(0)
A
0

I got same error while saving Bitmap to External Directory and found a helpful trick

private void save(Bitmap bitmap) {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String imageFileName = timeStamp + ".png";
    String path = MediaStore.Images.Media.insertImage(activity.getContentResolver(), bitmap, imageFileName, null);
    Uri uriimage = Uri.parse(path);
    // you made it, make  fun
    }

But this have a drawback i.e. you cant change the Directory it always save images to Pictures directory but if you got it fixed fill free to edit my code: Haa-ha-ha {I can't use emojis with my keyboard}, Good Day

Antoneantonella answered 3/10, 2020 at 1:58 Comment(1)
Don't forgot to give permissions else probability of down vote increases for my postAntoneantonella
K
0

Following are fixes i found first add these two lines in your AndroidManifest file

Than add the below line just after setContentView method

ActivityCompat.requestPermissions(FullImageActivity.this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_CODE);

and for saving the images in gallery use the below code

private void SaveImageToGallery() {
        BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
        Bitmap bitmap = drawable.getBitmap();
        FileOutputStream outputStream = null;
        File file = Environment.getExternalStorageDirectory();
        File dir = new File(file.getAbsolutePath()+"/folderName");
        dir.mkdirs();
        String filename = String.format("%d.jpg",System.currentTimeMillis());
        File outfile = new File(dir,filename);
        try{
            outputStream = new FileOutputStream(outfile);
            bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
            outputStream.flush();
            outputStream.close();
        }catch(Exception e){
            Log.d("SavingError", "SaveImageToGallery: "+e.getMessage());
        }
        Toast.makeText(this, "Image saved in folderName folder", Toast.LENGTH_SHORT).show();
    }
Kier answered 19/5, 2021 at 7:32 Comment(1)
and What about Gif and Animated Webp. these types will be converted into static imagesDreadfully
A
0

Don't use any numbers in the filename, it should work, but I don't know why it is happening.

Anglesey answered 28/7, 2023 at 11:36 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Colossian

© 2022 - 2024 — McMap. All rights reserved.