исключение java.io.FileNotFoundException, mkdir не работает должным образом?

#java #android

#java #Android

Вопрос:

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

Раньше это было:

 String path = STORAGE_PATH   "/DCMI"   "/Appdnp";
  

Я просто изменил на:

 String path = STORAGE_PATH   "/.vilarica"   "/Appdnp";
  

И это начало давать мне java.io.FileNotFoundException: /storage/emulated/0/.vilarica/Appdnp/5WmK6658f9eKcp2h0QghGToCKOi2.jpg: open failed: ENOENT (No such file or directory)

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

Путь к хранилищу:

 public static final String STORAGE_PATH = Environment.getExternalStorageDirectory().toString();
  

Но я не думаю, что это так, поскольку он работал раньше, и он правильно получает путь.
Это часть кода из класса, который представляет эти методы:

  private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(final byte[] data, Camera camera) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String path = STORAGE_PATH   "/.vilarica"   "/Appdnp";

                    writeFile(path, data);
                }
            }, "captureThread").start();
            startPreview();
        }
    };

    public void writeFile(String path, byte[] data) {
        Bitmap bitmap = null;
        if (data != null){
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        }

        if (bitmap != null){
            Matrix matrix = new Matrix();
            if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
                matrix.postRotate(90);
            }else if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT){
                matrix.postRotate(90);
                matrix.postScale(1, -1);
            }
            Bitmap rotateBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), matrix,false);
            saveBmp2SD(path, rotateBmp);
            rotateBmp.recycle();
        }
    }

    private void saveBmp2SD(String path, Bitmap bitmap){
        File file = new File(path);
        if (!file.exists()){
            file.mkdir();
        }
        String uid = user.getUid();
        //String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String fileName = path   "/"   uid   ".jpg";
        try {
            FileOutputStream fos = new FileOutputStream(fileName);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();
            bos.close();
            Log.i("TAG", "Take picture success!");
            Intent i = new Intent(this, DPCalc.class);
            i.putExtra("filename", fileName);
            i.putExtra("path", path);
            startActivity(i);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.e("TAG", "The save file for take picture does not exists!");
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("TAG", "Take picture fail!");
        }
    }
  

Комментарии:

1. Вы изменили только один каталог, но теперь вы находитесь на Android Q.

2. if (!file.exists()){ file.mkdir(); } Изменить на: if (!file.exists()){ if(!file.mkdirs()){ Toast(...could not make directory ..); return; } } . Бьюсь об заклад, вы увидите этот тост.

Ответ №1:

.mkdir() создает только один каталог, и в случае сбоя вы не получаете исключение, оно возвращает ‘false’. У реальной java есть соответствующий API, но я не думаю, что Android получает выгоду от этого лучшего API, он слишком сильно отстает от библиотек. Итак:

  1. Не вызывайте file.mkdir(); это file.getParent().mkdirs().
  2. Проверьте возвращаемое значение mkdirs().
  3. Обратите внимание, что ‘false’ в mkdirs() означает либо, что каталог уже существует и ничего не было сделано, либо что операция завершилась неудачей; невозможно определить, почему она завершилась неудачей.

Я упоминал, что этот API отстой, верно? Я думаю… теоретически вы могли бы написать свои собственные mkdirs, которые перемещаются по дереву «вручную». В качестве альтернативы, используйте if (!path.isDirectory()), чтобы проверить, существует ли он уже, и завершится ошибкой (без возможности сообщить пользователю, почему), если .mkdirs() возвращает false .

Комментарии:

1. Чтобы проверить возврат mkdirs, они возвращают логическое значение, но создание моего собственного API кажется мне слишком сложным = D. Протестирую это и посмотрю, что я получу, просто есть идеи, почему это работало раньше?

2. Пробовал использовать getParent(), но вроде бы он не компилировался, вместо этого я жестко запрограммировал путь как File file = new File(Environment.getExternalStorageDirectory(), "/.vilarica" "/Appdnp"); и, к удивлению, это работает. Я продолжу регистрацию не в приложении, чтобы увидеть, что было отправлено неправильно…

3. Хорошо, это звучит так: [1] каталог .vilarica уже существует (если бы это было не так, mkdirs() был бы обязательным, поскольку вам нужно было бы создать 2 каталога). [2] Вызов Environment.getExternalStorageDirectory() возвращал, например, «/foo/bar/», обратите внимание на косую черту в конце. новый файл («/hello /», «/world») создает «/ hello / world». объединение строки создает «/ hello //world», который отличается. Возможно, интерпретируется либо как неработающий путь, либо как «/world», которого не существует / вы не можете создавать mkdirs, поскольку у вас нет прав администратора.