Cómo crear un directorio automáticamente en la tarjeta SD


189

Estoy tratando de guardar mi archivo en la siguiente ubicación
FileOutputStream fos = new FileOutputStream("/sdcard/Wallpaper/"+fileName); pero obtengo la excepción java.io.FileNotFoundException
Sin embargo, cuando pongo la ruta como "/sdcard/"funciona.

Ahora supongo que no puedo crear el directorio automáticamente de esta manera.

¿Alguien puede sugerir cómo crear un directory and sub-directorycódigo de uso?

Respuestas:


449

Si crea un objeto File que envuelve el directorio de nivel superior, puede llamar a su método mkdirs () para construir todos los directorios necesarios. Algo como:

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

Nota: puede ser aconsejable usar Environment.getExternalStorageDirectory () para obtener el directorio "Tarjeta SD", ya que esto podría cambiar si aparece un teléfono que tiene algo más que una tarjeta SD (como flash incorporado, todo el iPhone) De cualquier manera, debe tener en cuenta que debe verificar para asegurarse de que realmente esté allí, ya que se puede extraer la tarjeta SD.

ACTUALIZACIÓN: desde el nivel 4 de API (1.6) también tendrá que solicitar el permiso. Algo como esto (en el manifiesto) debería funcionar:

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

1
Sí, las tabletas Samsung lanzadas posteriormente usan flash incorporado
CQM

2
no olvides agregar a AndroidManifest.xml el derecho a escribir stackoverflow.com/a/4435708/579646
max4ever

1
Parece que esto no funciona si tengo una subcarpeta, como /sdcard/com.my.code/data? ¿Cómo podría resolver esto?
lony

Además de crear este directorio también? ¿Hay un comando como 'force' en unix mkdir?
lony

44
No funciona en KitKat, tarjeta sd física externa.
celoftis

57

Tuve el mismo problema y solo quiero agregar que AndroidManifest.xml también necesita este permiso:

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

39

Esto es lo que funciona para mí.

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

en su manifiesto y el código a continuación

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

ruta es el nombre de la carpeta que desea crear. Si envió una ruta como MusicDownload ... Se convierte automáticamente en / sdcard / MusicDownload. Shajeel Afzal
shehzy

Lanza una excepción java.io.IO Excepción: error de apertura: ENOENT (No existe tal archivo o directorio)
Anand Savjani

24

En realidad, utilicé parte de @fiXedd asnwer y funcionó para mí:

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

Asegúrese de estar usando mkdirs () no mkdir () para crear la ruta completa


¿Cómo es esta "parte" de la respuesta @fixedd? Su respuesta fue usar File.mkdirs(). Luego mostró un ejemplo de uso.
Doomsknight

En realidad no puedo recordar cuál fue la diferencia, pero creo que hubo algunas ediciones ... Por cierto, mencioné que usé su respuesta para obtener la solución
Amt87

12

Con API 8 y superior, la ubicación de la tarjeta SD ha cambiado. La respuesta de @ fiXedd es buena, pero para un código más seguro, debe usar Environment.getExternalStorageState()para verificar si los medios están disponibles. Luego, puede usar getExternalFilesDir()para navegar al directorio que desee (suponiendo que esté utilizando API 8 o superior).

Puede leer más en la documentación del SDK .


8

Asegúrese de que el almacenamiento externo esté presente: 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

No olvide asegurarse de que no tiene caracteres especiales en los nombres de archivo / carpeta. Me pasó con ":" cuando estaba configurando los nombres de las carpetas usando variables

caracteres no permitidos en los nombres de archivo / carpeta

"* /: <>? \ |

U puede encontrar este código útil en tal caso.

El siguiente código elimina todo ":" y los reemplaza con "-"

//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 ya también lo intenté con: obtuve un error y finalmente encontré ese problema y lo eliminé: y todos los demás caracteres especiales.
Ganapathy C

6

Me enfrenté al mismo problema. Hay dos tipos de permisos en Android:

  • Peligroso (acceso a contactos, escritura en almacenamiento externo ...)
  • Normal (los permisos normales son aprobados automáticamente por Android, mientras que los permisos peligrosos deben ser aprobados por los usuarios de Android).

Aquí está la estrategia para obtener permisos peligrosos en Android 6.0

  • Compruebe si tiene el permiso otorgado
  • Si su aplicación ya tiene el permiso, continúe y realice normalmente.
  • Si su aplicación aún no tiene el permiso, solicite al usuario que apruebe
  • Escuche la aprobación del usuario en onRequestPermissionsResult

Aquí está mi caso: necesito escribir en un almacenamiento externo.

Primero, verifico si tengo el permiso:

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

Luego verifique la aprobación del usuario:

@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

Estaba enfrentando el mismo problema, no pude crear el directorio en Galaxy S pero pude crearlo con éxito en Nexus y Samsung Droid. Cómo lo arreglé fue agregando la siguiente línea de código:

File dir = new File(Environment.getExternalStorageDirectory().getPath()+"/"+getPackageName()+"/");
dir.mkdirs();

5
File sdcard = Environment.getExternalStorageDirectory();
File f=new File(sdcard+"/dor");
f.mkdir();

esto creará una carpeta llamada dor en su tarjeta sd. luego para buscar el archivo de eg- filename.json que se inserta manualmente en la carpeta dor . Me gusta:

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

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

y no olvides agregar código en manifiesto


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

Acabo de completar la publicación de Vijay ...


Manifiesto

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

Función

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

Uso

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

Podrías verificar si hay errores

if(createDirIfNotExists("mydir/")){
     //Directory Created Success
}
else{
    //Error
}

3

Esto hará que la carpeta en la tarjeta SD con el nombre de la carpeta que proporciones

File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Folder name");
        if (!file.exists()) {
            file.mkdirs();
        }

1

Puede usar / sdcard / en lugar de Environment.getExternalStorageDirectory ()

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

File dbdir = new File(DB_PATH);
dbdir.mkdirs();

44
No, no debe usar una ruta codificada en lugar de llamar a la API adecuada. Hacerlo introduce una dependencia imprudente de los detalles de una implementación particular.
Chris Stratton

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

        }
    });`
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.