Ошибка: open failed: ENOENT (Нет такого файла или каталога)

Я пытался создать файл для сохранения фотографий с камеры, оказалось, что я не могу создать файл. Но я действительно не могу найти ошибку. Можете ли вы взглянуть на нее и дать мне несколько советов?

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

И я добавил разрешение.

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

Метод всегда дает такие ошибки:

open failed: ENOENT (Нет такого файла или каталога)

Ответ 1

Возможно, каталог "Фотографии" еще не существует. Это не гарантировано.

В документации 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(); 

... так что это может быть так же просто, как добавить этот path.mkdirs() в ваш существующий код перед createTempFile.

Ответ 2

Заменить:

Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES)

С:

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

убедитесь, что вы звоните:

mkdirs() // and not mkdir()

Вот код, который должен работать для вас:

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

У меня был плохой опыт следования примеру, приведенному в документации Android Studio, и я обнаружил, что многие другие испытывают то же самое по этой конкретной теме здесь в stackoverflow, потому что даже если мы установим

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

проблема сохраняется в некоторых устройствах.

По моему опыту, этот пример работал, когда я попробовал его в режиме отладки, после того, как прошло еще 3 теста, так случилось, что моя SD внезапно повредилась, но я не думаю, что это связано с их примером (забавно). Я купил новую SD-карту и попробовал ее снова, только чтобы понять, что все еще и режим выпуска, и режим отладки делали один и тот же журнал ошибок: каталог не существует ENOENT. Наконец, мне пришлось самому создавать каталоги, которые будут содержать захваченные снимки с камеры телефона. И я был прав, это работает просто отлично.

Я надеюсь, что это поможет вам и другим людям в поисках ответов.

Ответ 3

Я использовал contentResolver с URI, и это сработало для меня. Увидел его в другом столбце, который я не могу найти.

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

Надеюсь, поможет....

Ответ 4

Я решил так:

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

Ответ 5

Попробуй это:

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

Ответ 6

У меня точно такая же проблема, может быть файл в галерее является миниатюрой. и кэш миниатюр не обновлен. так что получить файл не найден исключение

Ответ 7

Если вы используете kotlin, используйте функцию ниже. Вы должны указать путь для сохранения изображения, Растровое изображение (в данном случае изображение), и если вы хотите снизить качество изображения, укажите% age, то есть 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()
    }

надеюсь, что это сработает.