Як автоматично створити каталог на 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 Card", оскільки це може змінитися, якщо телефон прийде разом із 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? Як я міг це вирішити?
самотній

Окрім створення цього каталогу теж? Чи є в 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;
}

path - це назва папки, яку ви хочете створити. Якщо ви надіслали шлях, як MusicDownload .. Він автоматично стає / sdcard / MusicDownload. Shajeel Afzal
shehzy

Він кидає виняток 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 () для створення повного шляху


Як ця "частина" відповіді @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

Не забудьте переконатися, що у ваших іменах файлів / папок немає спеціальних символів. Сталося зі мною ":", коли я встановлював імена папок за допомогою змінних

Не дозволено символів у назвах файлів / папок

"* /: <>? \ |

U може вважати цей код корисним у такому випадку.

Наведений нижче код видаляє всі ":" і замінює їх на "-"

//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");
        }
    }

+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);

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

        }
    });`
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.