如何在SD卡上自动创建目录

194
我正试图将文件保存到以下位置: ```FileOutputStream fos = new FileOutputStream("/sdcard/Wallpaper/"+fileName);``` 但是我遇到了java.io.FileNotFoundException异常。 然而,当我将路径设置为"/sdcard/"时,它可以工作。
现在我假设我不能通过这种方式自动创建目录。
有人能建议如何使用代码创建一个目录和子目录吗?
13个回答

456
如果您创建一个包装顶级目录的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卡目录,因为如果手机配备了内置闪存(如iPhone),这可能会更改。无论哪种方式,您都应该记住需要检查确保它实际存在,因为SD卡可能已被移除。
更新:自API Level 4(1.6)以来,您还必须请求权限。像这样(在清单中)应该可以工作:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

1
是的,随后发布的三星平板电脑使用内置闪存。 - CQM
2
不要忘记在AndroidManifest.xml中添加写入权限 https://dev59.com/sHI95IYBdhLWcg3w1Bro#4435708 - max4ever
1
似乎如果我有一个子子文件夹,比如 /sdcard/com.my.code/data,这个方法就不起作用了?我该怎么解决呢? - lony
在API 19中完美运行。 - Luis Pena
4
不适用于KitKat系统上的外置物理SD卡。 - celoftis
显示剩余4条评论

57

我遇到了同样的问题,想补充一下AndroidManifest.xml也需要这个权限:

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

42

以下方法适用于我。

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

路径是您想要创建的文件夹的名称。如果您发送的路径类似于MusicDownload.。它会自动变成/sdcard/MusicDownload。Shajeel Afzal - shehzy
它抛出异常java.io.IOException:打开失败:ENOENT(没有这样的文件或目录) - Anand Savjani

24

实际上我使用了@fiXedd的答案的一部分,它对我有效:

  //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()。然后他展示了一个使用它的例子。 - IAmGroot
其实我记不清楚有什么区别了,但我想有一些编辑...顺便提一下,我提到我使用了他的答案来得到解决方案。 - 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");
        }
    }

+1,我也尝试使用冒号并遇到了错误,最终发现问题并删除了冒号和所有其他特殊字符。 - Ganapathy C

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

5

我面临着同样的问题,在Galaxy S上无法创建目录,但在Nexus和Samsung Droid上可以成功创建。我的解决方法是添加下面这行代码:

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

5
这将在sd卡中创建一个名为您提供的“文件夹名称”的文件夹。
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Folder name");
        if (!file.exists()) {
            file.mkdirs();
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接