Làm cách nào để bạn ghi vào một thư mục trên thẻ SD trong Android?


83

Tôi đang sử dụng mã sau để tải xuống tệp từ máy chủ của mình, sau đó ghi tệp đó vào thư mục gốc của thẻ SD, tất cả đều hoạt động tốt:

package com.downloader;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.Environment;
import android.util.Log;

public class Downloader {

    public void DownloadFile(String fileURL, String fileName) {
        try {
            File root = Environment.getExternalStorageDirectory();
            URL u = new URL(fileURL);
            HttpURLConnection c = (HttpURLConnection) u.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();
            FileOutputStream f = new FileOutputStream(new File(root, fileName));

            InputStream in = c.getInputStream();

            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = in.read(buffer)) > 0) {
                f.write(buffer, 0, len1);
            }
            f.close();
        } catch (Exception e) {
            Log.d("Downloader", e.getMessage());
        }

    }
}

Tuy nhiên, việc sử dụng Environment.getExternalStorageDirectory();có nghĩa là tệp sẽ luôn ghi vào thư mục gốc /mnt/sdcard. Có thể chỉ định một thư mục nào đó để ghi tệp vào không?

Ví dụ: /mnt/sdcard/myapp/downloads


12
Cũng cần phải nhớ để thêm các điều khoản trong biểu hiện cho điều này để làm việc .. <dụng-phép android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />
timemirror

Câu trả lời:


160
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File (sdCard.getAbsolutePath() + "/dir1/dir2");
dir.mkdirs();
File file = new File(dir, "filename");

FileOutputStream f = new FileOutputStream(file);
...

1
Đảm bảo sử dụng tất cả các chữ cái thường trong tên thư mục và tệp của bạn.
BeccaP

1
Tôi có thể biết nó có nghĩa là gì bởi "/ dir1 / dir2" và nếu không có điều này, tôi không thể lưu tệp của mình trong sdcard ah?
AndroidOptimist

17
Theo doc: Lưu ý: đừng nhầm lẫn với từ "bên ngoài" ở đây. Thư mục này có thể được coi là phương tiện / bộ nhớ được chia sẻ. Đây là một hệ thống tệp có thể chứa một lượng dữ liệu tương đối lớn và được chia sẻ trên tất cả các ứng dụng (không thực thi quyền). Theo truyền thống này là một thẻ SD , nhưng nó cũng có thể được thực hiện như xây dựng trong lưu trữ trong một thiết bị đó là khác biệt với bộ nhớ trong được bảo vệ và có thể được gắn kết như là một hệ thống tập tin trên một máy tính
mr5

1
@NeonWarge xem ở đây
mr5,

Cảnh báo: getExternalStorageDirectory()không được dùng nữa trong API 29.
Josh Correia

29

Thêm quyền vào Android Manifest

Thêm quyền WRITE_EXTERNAL_STORAGE này vào tệp kê khai ứng dụng của bạn.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="your.company.package"
    android:versionCode="1"
    android:versionName="0.1">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <!-- ... -->
    </application>
    <uses-sdk android:minSdkVersion="7" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest> 

Kiểm tra tính khả dụng của bộ nhớ ngoài

Bạn nên luôn kiểm tra tính khả dụng trước. Đoạn trích từ tài liệu Android chính thức về bộ nhớ ngoài .

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

Sử dụng máy ghi tệp

Cuối cùng, nhưng không kém phần quan trọng, hãy quên về FileOutputStreamvà sử dụng một FileWriterthay thế. Thông tin thêm về lớp đó tạo thành FileWriter javadoc . Bạn có thể muốn thêm một số xử lý lỗi khác tại đây để thông báo cho người dùng.

// get external storage file reference
FileWriter writer = new FileWriter(getExternalStorageDirectory()); 
// Writes the content to the file
writer.write("This\n is\n an\n example\n"); 
writer.flush();
writer.close();

1
Các tác giả của cuốn sách tôi đang đọc khuyên bạn nên sử dụng FileOutputStream(tốt, nó không bao gồm các lựa chọn thay thế). Tại sao tốt hơn nên sử dụng FileWriterthay thế - nó nhanh hơn / đáng tin cậy hơn / cái gì khác?
aga

3
@aga FileWritercó các phương thức tiện lợi để viết trực tiếp các Chuỗi, không có trên a FileOutputStream. Nếu bạn không viết các tệp văn bản, FileWriterthì không giúp được gì nhiều. Trên thực tế, nếu bạn đang viết một tệp hình ảnh , nó thực sự không thể thực hiện được với một FileWriter Tất nhiên, nếu bạn thực sự muốn có một API đẹp cho văn bản, hãy bọc của bạn FileOutputStreamtrong một tệp PrintStreamvà bạn sẽ có tất cả các phương pháp tương tự như System.out.
Ian McLaird

1
Tại sao tôi không thể tìm thấy tệp trên sdcard của mình sau khi tệp được ghi thành công?
Ai đó ở đâu đó

2

Tìm thấy câu trả lời ở đây - http://mytechead.wordpress.com/2014/01/30/android-create-a-file-and-write-to-external-storage/

Nó nói rằng,

/**

* Method to check if user has permissions to write on external storage or not

*/

public static boolean canWriteOnExternalStorage() {
   // get the state of your external storage
   String state = Environment.getExternalStorageState();
   if (Environment.MEDIA_MOUNTED.equals(state)) {
    // if storage is mounted return true
      Log.v("sTag", "Yes, can write to external storage.");
      return true;
   }
   return false;
}

và sau đó hãy sử dụng mã này để thực sự ghi vào bộ nhớ ngoài:

// get the path to sdcard
File sdcard = Environment.getExternalStorageDirectory();
// to this path add a new directory path
File dir = new File(sdcard.getAbsolutePath() + "/your-dir-name/");
// create this directory if not already created
dir.mkdir();
// create the file in which we will write the contents
File file = new File(dir, "My-File-Name.txt");
FileOutputStream os = outStream = new FileOutputStream(file);
String data = "This is the content of my file";
os.write(data.getBytes());
os.close();

Và đây là nó. Nếu bây giờ bạn truy cập thư mục / sdcard / your-dir-name / của mình, bạn sẽ thấy một tệp có tên - My-File-Name.txt với nội dung như được chỉ định trong mã.

Tái bút: - Bạn cần sự cho phép sau -

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

2
Thư mục /sdcard/không phải lúc nào cũng là sdcard.
SilverCorvus

Tôi đồng ý với Curly. Trên điện thoại của tôi, phương thức getExternalStorageDirectory trả về một bộ nhớ giả lập, không phải là sdcard.
Spindizzy

-1

Để tải tệp xuống Tải xuống hoặc Thư mục Nhạc trong thẻ SDCard

File downlodDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);// or DIRECTORY_PICTURES

Và đừng quên thêm các quyền này vào tệp kê khai

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

Điều này không tải xuống thư mục Tải xuống thay vì vào thẻ SD?
Josh Correia
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.