Android 读取 SD 卡上的文件

现代的几乎都自带 SD 卡或者可以额外的 SD 卡来扩充手机的存储容量,Android 也支持把 APP 安装到 SD 卡上

当我们使用 ContextopenFileInput() 或者 openFileOutput() 打开的文件输入输出流时,程序打开的都是 APP 数据文件夹中的文件 /data/data/<应用包名>/file

如果想存储的是视频,音乐等需要占用大量存储空间的,存到手机内存中显得很不明智,一般情况我们都会把这些大文件数据存储到 SD 扩展卡中

SD 卡读写步骤

  1. 读写前判断 SD 卡是是否插入,是否可读写

    Enviroment.getExternalStorageState().equals(Enviroment.MEDIA_MOUNTED);
    
  2. 获取 SD 卡的外部目录,同时获得 SD 卡路径

    Enviroment.getExternalStorageDirectory().getCanonicalPath();
    
  3. 使用 FileOutputStreamFileInputStreamFileReaderFileWriter 读写 SD 卡

  4. AndroidManifest.xml 中添加 SD 权限: 创建删除文件权限 和 读写数据权限

    <!-- 在 SD 卡中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!-- 往 SD 卡写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    

范例

我们写一个 demo 尝试在 SD 卡上创建文件 site.txt 并写入以下内容

简单教程,简单编程
  1. 创建一个 空的 Android 项目 cn.twle.android.WriteSDcard

  2. 修改 activity_main.xml 添加几个 TextView

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="请输入文件名"/>
    
        <EditText
            android:id="@+id/ms_filename"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="文件名"
            android:text="site.txt"/>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="请输入文件内容" />
    
        <EditText
            android:id="@+id/ms_filedata"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="简单教程,简单编程"
            android:hint="文件内容" />
    
        <Button
            android:id="@+id/btn_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="保存到 SD 卡" />
    
        <Button
            android:id="@+id/btn_clean"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="清空" />
    
        <Button
            android:id="@+id/btn_read"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="读取 SD 卡中的文件" />
    
    </LinearLayout>
    
  3. MainActivity.java 同一目录下新建文件 SDFileHelper.java 作为读写 SD 卡的帮助类

    package cn.twle.android.writesdcard;
    
    import android.content.Context;
    import android.os.Environment;
    import android.widget.Toast;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class SDFileHelper {
    
        private Context context;
    
        public SDFileHelper() {
        }
    
        public SDFileHelper(Context context) {
            super();
            this.context = context;
        }
    
        //SD卡写入文件的方法
        public void savaFileToSD(String filename, String filecontent) throws Exception {
            //如果手机已插入sd卡, app 具有读写 sd卡 的权限
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                filename = Environment.getExternalStorageDirectory().getCanonicalPath() + "/" + filename;
                //这里就不要用openFileOutput了,那个是往手机内存中写数据的
                FileOutputStream output = new FileOutputStream(filename);
                output.write(filecontent.getBytes());
                //String字符串以字节流的形式写入到输出流中
                output.close();
                //关闭输出流
            } else Toast.makeText(context, "SD卡不存在或者不可读写", Toast.LENGTH_SHORT).show();
        }
    
        //读取SD卡中文件的方法
        //定义读取文件的方法:
        public String readFromSD(String filename) throws IOException {
            StringBuilder sb = new StringBuilder("");
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                filename = Environment.getExternalStorageDirectory().getCanonicalPath() + "/" + filename;
                //打开文件输入流
                FileInputStream input = new FileInputStream(filename);
                byte[] temp = new byte[1024];
    
                int len = 0;
                //读取文件内容:
                while ((len = input.read(temp)) > 0) {
                    sb.append(new String(temp, 0, len));
                }
                //关闭输入流
                input.close();
            }
            return sb.toString();
        }
    
    }
    
  4. 修改 AndroidManifest.xml 加上读写 SD 卡的读写权限

    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
  5. 修改 MainActivity.java 实现相关逻辑

    package cn.twle.android.writesdcard;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import java.io.IOException;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
        private EditText ms_filename;
        private EditText ms_filedata;
        private Button btn_save;
        private Button btn_clean;
        private Button btn_read;
        private Context mContext;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mContext = getApplicationContext();
            bindViews();
        }
    
        private void bindViews() {
    
            ms_filename = (EditText) findViewById(R.id.ms_filename);
            ms_filedata = (EditText) findViewById(R.id.ms_filedata);
            btn_save = (Button) findViewById(R.id.btn_save);
            btn_clean = (Button) findViewById(R.id.btn_clean);
            btn_read = (Button) findViewById(R.id.btn_read);
    
            btn_save.setOnClickListener(this);
            btn_clean.setOnClickListener(this);
            btn_read.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.btn_clean:
                    ms_filename.setText("");
                    ms_filedata.setText("");
                    break;
                case R.id.btn_save:
                    String filename = ms_filename.getText().toString();
                    String filedetail = ms_filedata.getText().toString();
                    SDFileHelper sdHelper = new SDFileHelper(mContext);
                    try
                    {
                        sdHelper.savaFileToSD(filename, filedetail);
                        Toast.makeText(getApplicationContext(), "数据写入成功", Toast.LENGTH_SHORT).show();
                    }
                    catch(Exception e){
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(), "数据写入失败", Toast.LENGTH_SHORT).show();
                    }
                    break;
                case R.id.btn_read:
                    String detail = "";
                    SDFileHelper sdHelper2 = new SDFileHelper(mContext);
                    try
                    {
                        String filename2 = ms_filename.getText().toString();
    
                        detail = sdHelper2.readFromSD(filename2);
                    }
                    catch(IOException e){e.printStackTrace();}
                    Toast.makeText(getApplicationContext(), detail, Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }
    

运行 APP ,演示效果如下


DDMS 查看手机上的文件

DDMS 全名 Dalvik Debug Monitor Service,是 Android 开发环境中的 Dalvik 虚拟机调试监控服务

  1. 在最新的 Android Studio 3 中,DDMS 已经是顶级窗口之一了,一般会收缩在编辑器的右下角

  2. 单击 Device File Explore 就会展开当前设备根目录下的所有文件和目录

  3. 下拉找到一个叫 sdcard 的目录,这就是我们的 SD 卡目录,如果你没找到,那就在 /mnt/sdcard 目录

  4. 点击展开 sdcard 目录,一路往下拉一路观察,就会看到我们刚刚创建的文件 site.txt

    几乎就在最底部,还是名字起的好

  5. 双击打开 site.txt,如果是一般的文件,直接双击文件名就会打开

果然读写 SD 卡成功

读写 SD 卡的方法归纳

下面是我整理的一些读写 SD 卡的代码

  1. 获取SD卡的根目录

    String  sdcardRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
    
  2. 在 SD 卡上创建文件夹目录

    public File createDirOnSDCard(String dir)  
    {  
        File dirFile = new File(sdCardRoot + File.separator + dir +File.separator);  
        Log.v("createDirOnSDCard", sdCardRoot + File.separator + dir +File.separator);  
        dirFile.mkdirs();  
        return dirFile;  
    }
    
  3. 在 SD 卡上创建文件

    public File createFileOnSDCard(String fileName, String dir) throws IOException  
    {  
        File file = new File(sdCardRoot + File.separator + dir + File.separator + fileName);  
        Log.v("createFileOnSDCard", sdCardRoot + File.separator + dir + File.separator + fileName);  
        file.createNewFile();  
        return file;  
    }
    
  4. 判断文件是否存在于 SD 卡的某个目录

    public boolean isFileExist(String fileName, String path)  
    {  
        File file = new File(sdCardRoot + path + File.separator + fileName);  
        return file.exists();  
    }
    
  5. 将数据写入到 SD 卡指定目录文件

    public File writeData2SDCard(String path, String fileName, InputStream data)  
    {  
        File file = null;  
        OutputStream output = null;
    
        try {  
            createDirOnSDCard(path);  //创建目录  
            file = createFileOnSDCard(fileName, path);  //创建文件  
            output = new FileOutputStream(file);  
            byte buffer[] = new byte[2*1024];          //每次写2K数据  
            int temp;  
            while((temp = data.read(buffer)) != -1 )  
            {  
                output.write(buffer,0,temp);  
            }  
            output.flush();
    
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        finally{  
            try {  
                output.close();    //关闭数据流操作  
            } catch (Exception e2) {  
                e2.printStackTrace();  
            }  
        }
    
        return file;  
    }
    

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.