5. Android data storage (4) (file operation of memory card)

 1 Private storage space and public storage space

Android divides external storage into two areas, one is a public space accessible to all applications, and the other is a private space accessible only to the application itself.

Android creates a separate file directory for each application under the " Android/data " directory of the SD card, which is used to save the temporary files that the application needs to process. This file directory is created separately for each application. Only the current application can read and write files, and other applications are not allowed to read and write. Therefore, the "Android/data" directory is regarded as a private space on the external storage.

Android has strengthened the authority management of the SD card since 7.0. Apps need to declare the authority in advance before using the public control of the SD card, and need to enable the authority on the setting page. There is no need to set additional permissions to use the private space.

The public space has always existed, and the app in the private space is in the space

// 获取系统的公共存储路径
    String publicPath = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DOWNLOADS).toString();
    // 获取当前App的私有存储路径
    String privatePath = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString();
    TextView tv_file_path = findViewById(R.id.tv_file_path);
    String desc = "系统的公共存储路径位于" + publicPath +
            "\n\n当前App的私有存储路径位于" + privatePath;
    tv_file_path.setText(desc);

 2 Read and write text files on memory card

package com.example.chapter06.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

public class FileUtil {

    // 把字符串保存到指定路径的文本文件
    public static void saveText(String path, String txt) {
        // 根据指定的文件路径构建文件输出流对象
        try (FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(txt.getBytes()); // 把字符串写入文件输出流
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从指定路径的文本文件中读取内容字符串
    public static String openText(String path) {
        String readStr = "";
        // 根据指定的文件路径构建文件输入流对象
        try (FileInputStream fis = new FileInputStream(path)) {
            byte[] b = new byte[fis.available()];
            fis.read(b); // 从文件输入流读取字节数组
            readStr = new String(b); // 把字节数组转换为字符串
        } catch (Exception e) {
            e.printStackTrace();
        }
        return readStr; // 返回文本文件中的文本字符串
    }

    // 把位图数据保存到指定路径的图片文件
    public static void saveImage(String path, Bitmap bitmap) {
        // 根据指定的文件路径构建文件输出流对象
        try (FileOutputStream fos = new FileOutputStream(path)) {
            // 把位图数据压缩到文件输出流中
            bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从指定路径的图片文件中读取位图数据
    public static Bitmap openImage(String path) {
        Bitmap bitmap = null; // 声明一个位图对象
        // 根据指定的文件路径构建文件输入流对象
        try (FileInputStream fis = new FileInputStream(path)) {
            bitmap = BitmapFactory.decodeStream(fis); // 从文件输入流中解码位图数据
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap; // 返回图片文件中的位图数据
    }

    public static List<File> getFileList(String path, String[] extendArray) {
        List<File> displayedContent = new ArrayList<File>();
        File[] files = null;
        File directory = new File(path);
        if (extendArray != null && extendArray.length > 0) {
            FilenameFilter fileFilter = getTypeFilter(extendArray);
            files = directory.listFiles(fileFilter);
        } else {
            files = directory.listFiles();
        }

        if (files != null) {
            for (File f : files) {
                if (!f.isDirectory() && !f.isHidden()) {
                    displayedContent.add(f);
                }
            }
        }
        // 按照最后修改时间排序
        Collections.sort(displayedContent, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return (o1.lastModified() > o2.lastModified()) ? -1 : 1;
            }
        });
        return displayedContent;
    }

    public static FilenameFilter getTypeFilter(String[] extendArray) {
        final ArrayList<String> fileExtensions = new ArrayList<String>();
        for (int i = 0; i < extendArray.length; i++) {
            fileExtensions.add(extendArray[i]);
        }
        FilenameFilter fileNameFilter = new FilenameFilter() {
            @Override
            public boolean accept(File directory, String fileName) {
                boolean matched = false;
                File f = new File(String.format("%s/%s",
                        directory.getAbsolutePath(), fileName));
                matched = f.isDirectory();
                if (!matched) {
                    for (String s : fileExtensions) {
                        s = String.format(".{0,}\\%s$", s);
                        s = s.toUpperCase(Locale.getDefault());
                        fileName = fileName.toUpperCase(Locale.getDefault());
                        matched = fileName.matches(s);
                        if (matched) {
                            break;
                        }
                    }
                }
                return matched;
            }
        };
        return fileNameFilter;
    }

}
package com.example.chapter06;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter06.util.DateUtil;
import com.example.chapter06.util.FileUtil;
import com.example.chapter06.util.ToastUtil;

import java.io.File;

@SuppressLint("SetTextI18n")
public class FileWriteActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
    private EditText et_name;
    private EditText et_age;
    private EditText et_height;
    private EditText et_weight;
    private boolean bMarried = false;
    private String[] typeArray = {"未婚", "已婚"};
    private String mPath; // 私有目录路径
    String file_path;
    private TextView tv_path;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_file_write);
        et_name = findViewById(R.id.et_name);
        et_age = findViewById(R.id.et_age);
        et_height = findViewById(R.id.et_height);
        et_weight = findViewById(R.id.et_weight);
        tv_path = findViewById(R.id.tv_path);
        CheckBox ck_married = findViewById(R.id.ck_married);
        ck_married.setOnCheckedChangeListener(this);
        findViewById(R.id.btn_save).setOnClickListener(this);
        findViewById(R.id.btn_read).setOnClickListener(this);
        // 获取当前App的私有下载目录
       // mPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()+"/";
        mPath = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString()+"/";
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        bMarried = isChecked;
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_save) {
            String name = et_name.getText().toString();
            String age = et_age.getText().toString();
            String height = et_height.getText().toString();
            String weight = et_weight.getText().toString();
            if (TextUtils.isEmpty(name)) {
                ToastUtil.show(this, "请先填写姓名");
                return;
            } else if (TextUtils.isEmpty(age)) {
                ToastUtil.show(this, "请先填写年龄");
                return;
            } else if (TextUtils.isEmpty(height)) {
                ToastUtil.show(this, "请先填写身高");
                return;
            } else if (TextUtils.isEmpty(weight)) {
                ToastUtil.show(this, "请先填写体重");
                return;
            }
            String content = String.format(" 姓名:%s\n 年龄:%s\n 身高:%scm\n 体重:%skg\n 婚否:%s\n 注册时间:%s\n",
                    name, age, height, weight, typeArray[bMarried?1:0], DateUtil.getNowDateTime("yyyy-MM-dd HH:mm:ss"));
            file_path = mPath + DateUtil.getNowDateTime("") + ".txt";
            FileUtil.saveText(file_path, content); // 把字符串内容保存为文本文件
            tv_path.setText("用户注册信息文件的保存路径为:\n" + file_path);
            ToastUtil.show(this, "数据已写入存储卡文件");
        }

        if(v.getId()==R.id.btn_read){
            tv_path.setText(FileUtil.openText(file_path));
        }
    }

}

 

 .3 Read and write image files on the memory card

package com.example.chapter06.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

public class FileUtil {

    // 把字符串保存到指定路径的文本文件
    public static void saveText(String path, String txt) {
        // 根据指定的文件路径构建文件输出流对象
        try (FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(txt.getBytes()); // 把字符串写入文件输出流
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从指定路径的文本文件中读取内容字符串
    public static String openText(String path) {
        String readStr = "";
        // 根据指定的文件路径构建文件输入流对象
        try (FileInputStream fis = new FileInputStream(path)) {
            byte[] b = new byte[fis.available()];
            fis.read(b); // 从文件输入流读取字节数组
            readStr = new String(b); // 把字节数组转换为字符串
        } catch (Exception e) {
            e.printStackTrace();
        }
        return readStr; // 返回文本文件中的文本字符串
    }

    // 把位图数据保存到指定路径的图片文件
    public static void saveImage(String path, Bitmap bitmap) {
        // 根据指定的文件路径构建文件输出流对象
        try (FileOutputStream fos = new FileOutputStream(path)) {
            // 把位图数据压缩到文件输出流中
            bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从指定路径的图片文件中读取位图数据
    public static Bitmap openImage(String path) {
        Bitmap bitmap = null; // 声明一个位图对象
        // 根据指定的文件路径构建文件输入流对象
        try (FileInputStream fis = new FileInputStream(path)) {
            bitmap = BitmapFactory.decodeStream(fis); // 从文件输入流中解码位图数据
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap; // 返回图片文件中的位图数据
    }

   
     
}
package com.example.chapter06;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.chapter06.util.DateUtil;
import com.example.chapter06.util.FileUtil;
import com.example.chapter06.util.ToastUtil;

public class ImageWriteActivity extends AppCompatActivity implements View.OnClickListener {
    private ImageView iv_content;
    private TextView tv_path;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_write);
        iv_content = findViewById(R.id.iv_content);
        iv_content.setImageResource(R.mipmap.huawei); // 设置图像视图的图片资源
        tv_path = findViewById(R.id.tv_path);
        findViewById(R.id.btn_save).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_save) {
            // 获取当前App的私有下载目录
            String path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/";
            // 从指定的资源文件中获取位图对象
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.huawei);
            String file_path = path + DateUtil.getNowDateTime("") + ".jpeg";
            FileUtil.saveImage(file_path, bitmap); // 把位图对象保存为图片文件
            tv_path.setText("图片文件的保存路径为:\n" + file_path);
            ToastUtil.show(this, "图片已写入存储卡文件");
        }
    }

}
package com.example.chapter06;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.chapter06.util.FileUtil;
import com.example.chapter06.util.ToastUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class ImageReadActivity extends AppCompatActivity implements View.OnClickListener {
    private final static String TAG = "ImageReadActivity";
    private TextView tv_content;
    private ImageView iv_content;
    private String mPath; // 私有目录路径
    private List<File> mFilelist = new ArrayList<File>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_read);
        tv_content = findViewById(R.id.tv_content);
        iv_content = findViewById(R.id.iv_content);
        findViewById(R.id.btn_delete).setOnClickListener(this);
        // 获取当前App的私有下载目录
        mPath = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/";
        showFileContent(); // 显示最新的图片文件内容
    }

    // 显示最新的图片文件内容
    private void showFileContent() {
        // 获得指定目录下面的所有图片文件
        mFilelist = FileUtil.getFileList(mPath, new String[]{".jpeg"});
        if (mFilelist.size() > 0) {
            // 打开并显示选中的图片文件内容
            String file_path = mFilelist.get(0).getAbsolutePath();
            tv_content.setText("找到最新的图片文件,路径为"+file_path);
            // 显示存储卡图片文件的第一种方式:直接调用setImageURI方法
            //iv_content.setImageURI(Uri.parse(file_path)); // 设置图像视图的路径对象
            // 第二种方式:先调用BitmapFactory.decodeFile获得位图,再调用setImageBitmap方法
            //Bitmap bitmap = BitmapFactory.decodeFile(file_path);
            //iv_content.setImageBitmap(bitmap); // 设置图像视图的位图对象
            // 第三种方式:先调用FileUtil.openImage获得位图,再调用setImageBitmap方法
            Bitmap bitmap = FileUtil.openImage(file_path);
            iv_content.setImageBitmap(bitmap); // 设置图像视图的位图对象
        } else {
            tv_content.setText("私有目录下未找到任何图片文件");
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_delete) {
            for (int i = 0; i < mFilelist.size(); i++) {
                // 获取该文件的绝对路径字符串
                String file_path = mFilelist.get(i).getAbsolutePath();
                File f = new File(file_path);
                if (!f.delete()) { // 删除文件,并判断是否成功删除
                    Log.d(TAG, "file_path=" + file_path + ", delete failed");
                }
            }
            ToastUtil.show(this, "已删除私有目录下的所有图片文件");
        }
    }

}

 

 

Guess you like

Origin blog.csdn.net/weixin_62190821/article/details/127266199