Как автоматически создать каталог на SD-карте

189

Я пытаюсь сохранить свой файл в следующем месте,
FileOutputStream fos = new FileOutputStream("/sdcard/Wallpaper/"+fileName); но получаю исключение, java.io.FileNotFoundException
однако, когда я ставлю путь, как "/sdcard/"он работает.

Теперь я предполагаю, что я не могу создать каталог автоматически таким образом.

Может кто-нибудь подсказать, как создать directory and sub-directoryиспользующий код?

Кшитий Аггарвал
источник

Ответы:

449

Если вы создаете объект File, который оборачивает каталог верхнего уровня, вы можете вызвать его метод mkdirs () для создания всех необходимых каталогов. Что-то вроде:

// create a File object for the parent directory
File wallpaperDirectory = new File("/sdcard/Wallpaper/");
// have the object build the directory structure, if needed.
wallpaperDirectory.mkdirs();
// create a File object for the output file
File outputFile = new File(wallpaperDirectory, filename);
// now attach the OutputStream to the file object, instead of a String representation
FileOutputStream fos = new FileOutputStream(outputFile);

Примечание. Возможно, было бы разумно использовать Environment.getExternalStorageDirectory () для получения каталога «SD-карта», поскольку это может измениться, если появится телефон с чем-то иным, чем SD-карта (например, встроенная флэш-память, iPhone). В любом случае вы должны помнить, что вам нужно проверить, чтобы убедиться, что это действительно так, поскольку SD-карта может быть удалена.

ОБНОВЛЕНИЕ: Начиная с API уровня 4 (1.6), вам также придется запрашивать разрешение. Примерно так (в манифесте) должно работать:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Джереми Логан
источник
1
да, впоследствии выпущенные планшеты Samsung используют встроенную вспышку
CQM
2
не забудьте добавить в AndroidManifest.xml право писать stackoverflow.com/a/4435708/579646
max4ever
1
Это швы, это не работает, если у меня есть подпапка, как /sdcard/com.my.code/data? Как я мог решить это?
одинокий
Помимо создания этого каталога тоже? Есть ли такая команда, как 'force' в unix mkdir?
одинокий
4
Не работает на KitKat, внешняя, физическая SDCard.
celoftis
57

Возникла та же проблема, и я просто хочу добавить, что AndroidManifest.xml также нуждается в этом разрешении:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Даниил
источник
39

Вот что у меня работает.

 uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" 

в вашем манифесте и код ниже

public static boolean createDirIfNotExists(String path) {
    boolean ret = true;

    File file = new File(Environment.getExternalStorageDirectory(), path);
    if (!file.exists()) {
        if (!file.mkdirs()) {
            Log.e("TravellerLog :: ", "Problem creating Image folder");
            ret = false;
        }
    }
    return ret;
}
Виджай Кумар AB
источник
путь - это имя папки, которую вы хотите создать. Если вы отправили путь, такой как MusicDownload .. Он автоматически становится / sdcard / MusicDownload. Shajeel Afzal
шехзи
Выдает исключение java.io.IOException: открыть не удалось: ENOENT (нет такого файла или каталога)
Anand Savjani
24

На самом деле я использовал часть @fiXedd asnwer, и у меня это сработало:

  //Create Folder
  File folder = new File(Environment.getExternalStorageDirectory().toString()+"/Aqeel/Images");
  folder.mkdirs();

  //Save the path as a string value
  String extStorageDirectory = folder.toString();

  //Create New file and name it Image2.PNG
  File file = new File(extStorageDirectory, "Image2.PNG");

Убедитесь, что вы используете mkdirs (), а не mkdir () для создания полного пути

Amt87
источник
Как эта «часть» ответа @fixedd? Его ответом было использование File.mkdirs(). Затем он показал пример его использования.
Doomsknight
На самом деле я не могу вспомнить, в чем была разница, но я думаю, что были некоторые правки ... Кстати, я упомянул, что использовал его ответ, чтобы получить решение
Amt87
12

С API 8 и выше, местоположение SD-карты изменилось. Ответ @ fiXedd хорош, но для более безопасного кода вы должны использовать его, Environment.getExternalStorageState()чтобы проверить, доступен ли носитель. Затем вы можете использовать getExternalFilesDir()для перехода к нужному каталогу (при условии, что вы используете API 8 или выше).

Вы можете прочитать больше в документации SDK .

Ник Руис
источник
8

Убедитесь в наличии внешнего хранилища: http://developer.android.com/guide/topics/data/data-storage.html#filesExternal

private boolean isExternalStoragePresent() {

        boolean mExternalStorageAvailable = false;
        boolean mExternalStorageWriteable = false;
        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // We can read and write the media
            mExternalStorageAvailable = mExternalStorageWriteable = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // We can only read the media
            mExternalStorageAvailable = true;
            mExternalStorageWriteable = false;
        } else {
            // Something else is wrong. It may be one of many other states, but
            // all we need
            // to know is we can neither read nor write
            mExternalStorageAvailable = mExternalStorageWriteable = false;
        }
        if (!((mExternalStorageAvailable) && (mExternalStorageWriteable))) {
            Toast.makeText(context, "SD card not present", Toast.LENGTH_LONG)
                    .show();

        }
        return (mExternalStorageAvailable) && (mExternalStorageWriteable);
    }
Парт Мехта
источник
6

Не забудьте убедиться, что в именах файлов / папок нет специальных символов. Произошло со мной с «:», когда я устанавливал имена папок с помощью переменных

недопустимые символы в именах файлов / папок

"* /: <>? \ |

Вы можете найти этот код полезным в таком случае.

Приведенный ниже код удаляет все ":" и заменяет их на "-"

//actualFileName = "qwerty:asdfg:zxcvb" say...

    String[] tempFileNames;
    String tempFileName ="";
    String delimiter = ":";
    tempFileNames = actualFileName.split(delimiter);
    tempFileName = tempFileNames[0];
    for (int j = 1; j < tempFileNames.length; j++){
        tempFileName = tempFileName+" - "+tempFileNames[j];
    }
    File file = new File(Environment.getExternalStorageDirectory(), "/MyApp/"+ tempFileName+ "/");
    if (!file.exists()) {
        if (!file.mkdirs()) {
        Log.e("TravellerLog :: ", "Problem creating Image folder");
        }
    }
Praveen
источник
+1 Я тоже попробовал с: и получил ошибку и, наконец, нашел эту проблему и удалил: и все другие специальные символы.
Ганапатия C
6

Я столкнулся с той же проблемой. В Android есть два типа разрешений:

  • Опасно (доступ к контактам, запись во внешнее хранилище ...)
  • Нормальный (Обычные разрешения автоматически утверждаются Android, в то время как опасные разрешения должны быть одобрены пользователями Android.)

Вот стратегия получения опасных разрешений в Android 6.0

  • Проверьте, есть ли у вас разрешение
  • Если вашему приложению уже предоставлено разрешение, продолжайте и работайте нормально.
  • Если ваше приложение еще не имеет разрешения, попросите пользователя подтвердить
  • Слушайте одобрение пользователя в onRequestPermissionsResult

Вот мой случай: мне нужно написать на внешнее хранилище.

Сначала я проверяю, есть ли у меня разрешение:

...
private static final int REQUEST_WRITE_STORAGE = 112;
...
boolean hasPermission = (ContextCompat.checkSelfPermission(activity,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
    ActivityCompat.requestPermissions(parentActivity,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_WRITE_STORAGE);
}

Затем проверьте одобрение пользователя:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
    {
        case REQUEST_WRITE_STORAGE: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                //reload my activity with permission granted or use the features what required the permission
            } else
            {
                Toast.makeText(parentActivity, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }
    }    
}
Саид Абдул Басит
источник
5

Я столкнулся с той же проблемой, не смог создать каталог на Galaxy S, но смог успешно создать его на Nexus и Samsung Droid. Как я это исправил, добавив следующую строку кода:

File dir = new File(Environment.getExternalStorageDirectory().getPath()+"/"+getPackageName()+"/");
dir.mkdirs();
Гарима Шривастава
источник
5
File sdcard = Environment.getExternalStorageDirectory();
File f=new File(sdcard+"/dor");
f.mkdir();

это создаст папку с именем dor в вашей SDCard. затем извлечь файл для eg- filename.json, который вручную вставляется в папку dor . Подобно:

 File file1 = new File(sdcard,"/dor/fitness.json");
 .......
 .....

<использует-разрешение android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />

и не забудьте добавить код в манифест

Джаянт Сингх
источник
4
     //Create File object for Parent Directory
File wallpaperDir = new File(Environment.getExternalStorageDirectory().getAbsoluteFile() +File.separator + "wallpaper");
if (!wallpaperDir.exists()) {
wallpaperDir.mkdir();
}


File out = new File(wallpaperDir, wallpaperfile);
FileOutputStream outputStream = new FileOutputStream(out);
vikseln
источник
3

Просто завершаю пост Виджая ...


манифест

uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"

функция

public static boolean createDirIfNotExists(String path) {
    boolean ret = true;

    File file = new File(Environment.getExternalStorageDirectory(), path);
    if (!file.exists()) {
        if (!file.mkdirs()) {
            Log.e("TravellerLog :: ", "Problem creating Image folder");
            ret = false;
        }
    }
    return ret;
}

использование

createDirIfNotExists("mydir/"); //Create a directory sdcard/mydir
createDirIfNotExists("mydir/myfile") //Create a directory and a file in sdcard/mydir/myfile.txt

Вы можете проверить на ошибки

if(createDirIfNotExists("mydir/")){
     //Directory Created Success
}
else{
    //Error
}
Исмаэль Ди Вита
источник
3

Это сделает папку в SDCard с именем папки, которую вы предоставляете.

File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Folder name");
        if (!file.exists()) {
            file.mkdirs();
        }
Швета Чаухан
источник
1

Вы можете использовать / sdcard / вместо Environment.getExternalStorageDirectory ()

private static String DB_PATH = "/sdcard/Android/data/com.myawesomeapp.app/";

File dbdir = new File(DB_PATH);
dbdir.mkdirs();
Питер Дриннан
источник
4
Нет, вы не должны использовать жестко закодированный путь вместо вызова правильного API. Это вводит неразумную зависимость от деталей конкретной реализации.
Крис Страттон
1
ivmage.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent i = new Intent(
                    Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

            startActivityForResult(i, RESULT_LOAD_IMAGE_ADD);

        }
    });`
Вишну Намбудири
источник