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?

Kshitij Aggarwal
fuente

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" />
Jeremy Logan
fuente
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" />
Daniel
fuente
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;
}
Vijay Kumar AB
fuente
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

Amt87
fuente
¿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 .

Nick Ruiz
fuente
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);
    }
Parth mehta
fuente
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");
        }
    }
Praveen
fuente
+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();
            }
        }
    }    
}
Syed Abdul Basit
fuente
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();
Garima Srivastava
fuente
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

jayant singh
fuente
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
fuente
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
}
Ismael Di Vita
fuente
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();
        }
Shweta Chauhan
fuente
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();
Peter Drinnan
fuente
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);

        }
    });`
Vishnu Namboodiri
fuente