วิธีสร้างไดเรกทอรีโดยอัตโนมัติในการ์ด SD


189

ฉันกำลังพยายามบันทึกไฟล์ของฉันไปยังตำแหน่งต่อไปนี้
FileOutputStream fos = new FileOutputStream("/sdcard/Wallpaper/"+fileName); แต่ฉันได้รับการยกเว้นjava.io.FileNotFoundException
อย่างไรก็ตามเมื่อฉันใส่พา ธ ในการ"/sdcard/"ทำงาน

ตอนนี้ฉันสมมติว่าฉันไม่สามารถสร้างไดเรกทอรีโดยอัตโนมัติด้วยวิธีนี้

มีคนแนะนำวิธีสร้างdirectory and sub-directoryรหัสโดยใช้ได้ไหม

คำตอบ:


449

หากคุณสร้างวัตถุไฟล์ที่หุ้มไดเรกทอรีระดับบนสุดคุณสามารถเรียกว่าเป็นวิธีการ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 Card (เช่นแฟลชในตัว 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? ฉันจะแก้ปัญหานี้ได้อย่างไร
lony

นอกจากนี้การสร้างไดเรกทอรีนี้ด้วยหรือไม่ มีคำสั่งเช่น 'force' ใน unix mkdir หรือไม่?
lony

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

อย่าลืมตรวจสอบให้แน่ใจว่าคุณไม่มีตัวอักษรพิเศษในชื่อไฟล์ / โฟลเดอร์ของคุณ เกิดขึ้นกับฉันด้วย ":" เมื่อฉันตั้งชื่อโฟลเดอร์โดยใช้ตัวแปร

ไม่อนุญาตให้ใช้อักขระในชื่อไฟล์ / โฟลเดอร์

"* /: <>? \ |

คุณอาจพบว่ารหัสนี้มีประโยชน์ในกรณีเช่นนี้

รหัสด้านล่างจะลบ ":" ทั้งหมดและแทนที่ด้วย "-"

//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 ฉันลองด้วย: และมีข้อผิดพลาดและในที่สุดก็พบปัญหานั้นและนำออก: และตัวอักษรพิเศษอื่น ๆ ทั้งหมด
Ganapathy 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 ของคุณ จากนั้นเพื่อดึงไฟล์สำหรับเช่น - filename.json ซึ่งถูกแทรกด้วยตนเองในโฟลเดอร์dor ชอบ:

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

<ใช้สิทธิ์อนุญาต Android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />

และอย่าลืมเพิ่มรหัสในไฟล์ Manifest


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

เพิ่งโพสต์ของ Vijay ให้เสร็จ ...


ประจักษ์

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 ที่เหมาะสม การทำเช่นนี้เป็นการแนะนำการพึ่งพารายละเอียดของการใช้งานที่ไม่ฉลาด
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);

        }
    });`
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.