六 文件存储

一、实验目的及任务

1、 掌握文件内存的使用

2、 掌握SD卡存储的使用

3、掌握SQLite数据库的增删改查操作。熟悉SQLiteDatabase操作类,SQLiteOpenHelper辅助类的使用

二、实验环境

1、 Jdk

2、 Android Studio

3、 Android SDK

三、实验步骤

使用File类开发一个文件浏览器,用于查看SD卡中的文件信息。

注意:使用ListView控件来显示指定目录中的全部文件和文件夹。

实验结果:

Android 写文件 外部存储 android文件存储实验报告_java

代码:

项目目录:

Android 写文件 外部存储 android文件存储实验报告_Android 写文件 外部存储_02

根布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/tva"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50sp"
            android:orientation="horizontal"
            android:paddingTop="15sp">
            <ImageView
                android:id="@+id/backArrow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_keyboard_arrow_left_black_24dp"
                android:onClick="goBack"/>
            <TextView
                android:layout_marginLeft="80sp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="当前路径为: "/>
            <TextView
                android:id="@+id/thePath"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="   "/>
        </LinearLayout>
        <ListView
            android:id="@+id/mylistA"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        </ListView>
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

list View 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <LinearLayout
        android:id="@+id/ll_view"
        android:gravity="center"
        android:layout_margin="10dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:background="#FAFAFA"
            android:id="@+id/fileImg"
            android:layout_width="60sp"
            android:layout_height="60sp" />
        <LinearLayout
            android:layout_width="250sp"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_marginLeft="30sp">
            <TextView
                android:id="@+id/fileName"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="文件名"
                android:paddingTop="20sp"/>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

Java代码:

import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

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

//使用File类开发一个文件浏览器,用于查看SD卡中的文件信息。
//注意:使用ListView控件来显示指定目录中的全部文件和文件夹。

//只要求查看文件目录(不要求增删改查), 只要求在SD中
public class MainActivity extends AppCompatActivity {

    LinearLayout linearLayoutA;//获取整个根布局linearLayout用户构建listView
    TextView thePath;//赋值当前路径

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        linearLayoutA = findViewById(R.id.tva);//整个根布局linearLayout
        thePath = findViewById(R.id.thePath);//跟布局中显示的路径
        init();
    }

    public void init(){//初始化
        thePath.setText(getSdCardPath());//将SD卡的根路径直接赋值给路径, 因为这是初始化
        List<Map<String,Object>> listItems=new ArrayList<>();//用于构建list view
        String[] childs = getChilds(getSdCardPath());//得到根路径下所有的文件名称
        if (childs != null){//只要不是空
            for(int i=0;i<childs.length;i++){//就将所有的这一级目录下所有的文件名都放到list view中
                Map<String,Object> listItem=new HashMap<>();
                listItem.put("fileName",childs[i]);
                if(childs[i].contains(".") && childs[i].charAt(0)!='.'){//如果包含点就说明是个文件而不是文件夹
                    String type = childs[i].split(".")[1];//得到文件类型
                    if(type.equals("jpg") || type.equals("png")){//如果是图片的话就给它图片的图标
                        listItem.put("fileImg",R.drawable.ic_image_black_24dp);
                    }
                }else { //不是图片
                    System.out.println("此处的文件路径为:                   "+getSdCardPath()+"/"+childs[i]);
                    File file = new File(getSdCardPath()+"/"+childs[i]);//将这个文件取出来 就能判断是文件夹还是文件
                    if(file.isDirectory()){//是文件夹 给它文件夹的图标
                        listItem.put("fileImg",R.drawable.ic_folder_black_24dp);
                    }else {//是非图片的文件 给它普通文件的图标
                        listItem.put("fileImg",R.drawable.ic_insert_drive_file_black_24dp);
                    }
                }
                listItems.add(listItem);
            }
        }
        //new一个SimpleAdapter对象用于适配 list view
        //这个对象的构造函数需要的参数包括
        //当前应用的上下文ApplicationContext
        //list view要放的 map元素(此处的元素 包含一个文件图标和一个文件名称组成的map)
        //list view所对应的layout
        //map元素 的所有的index名
        //map元素 的所有的index所对应的在list view的layout中的id, 通过这样找到位置
        SimpleAdapter simpleAdapter=new SimpleAdapter(getApplicationContext(), listItems, R.layout.message,
                new String[]{"fileName","fileImg"}, new int[]{R.id.fileName, R.id.fileImg});
        ListView myList = findViewById(R.id.mylistA);//new一个list view对象,
        // 参数需要引用了这个list view的layout中这个list view的id
        myList.setAdapter(simpleAdapter);//关键的一步, ListView需要set前面我们new的simpleAdapter对象
        myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {//用于打开下一个文件的操作
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                TextView fileName = view.findViewById(R.id.fileName);
                //在Activity当中使用findViewById()方法貌似不一定需要由view对象来点,
                //但是如果直接使用, 在listView中获取到的值可能和想要的值不一样(会只获取第一个值, 也就是这里的Android文件夹)
                String theName = fileName.getText().toString();
                File theFile = new File(getSdCardPath()+"/"+theName);//锁定根部录下的这个文件, 判断是不是文件
                if(theFile.isDirectory()){
                    System.out.println("判断为路径, 即将进入路径:            "+getSdCardPath()+"/"+theName);
                    clickIn(getSdCardPath()+"/"+theName);
                }else {//发现是个文件 而不是文件夹 不能进入
                    Toast toast=Toast.makeText(getApplicationContext(), "不能打开文件", Toast.LENGTH_SHORT);
                    toast.show();
                }
            }
        });
    }

    //这个方法和init()方法神似, 只不过init()方法实在根文件路径下的, 这个方法有一个参数filePath, 实在根路径下的又一个路径, 也就说是进入了人某一个文件夹
    public void clickIn(String filePath){
        System.out.println("进入了clickIn()方法, 此时的文件路径为:       "+filePath);
        thePath.setText(filePath);
        List<Map<String,Object>> listItems=new ArrayList<>();
        String[] childs = getChilds(filePath);
        if (childs != null){
            for(int i=0;i<childs.length;i++){
                Map<String,Object> listItem=new HashMap<>();
                listItem.put("fileName",childs[i]);
                if(childs[i].contains(".") && childs[i].charAt(0)!='.'){
                    System.out.println("childs[i]:                             "+childs[i]);
                    String type = childs[i].split(".")[1];
                    if(type.equals("jpg") || type.equals("png")){
                        listItem.put("fileImg",R.drawable.ic_image_black_24dp);
                    }
                }else {
                    System.out.println("此处的文件路径为:                   "+filePath+"/"+childs[i]);
                    File file = new File(filePath+"/"+childs[i]);
                    if(file.isDirectory()){
                        listItem.put("fileImg",R.drawable.ic_folder_black_24dp);
                    }else {
                        listItem.put("fileImg",R.drawable.ic_insert_drive_file_black_24dp);
                    }
                }
                listItems.add(listItem);
            }
        }
        SimpleAdapter simpleAdapter=new SimpleAdapter(getApplicationContext(), listItems, R.layout.message,
                new String[]{"fileName","fileImg"}, new int[]{R.id.fileName, R.id.fileImg});
        ListView myList = findViewById(R.id.mylistA);
        myList.setAdapter(simpleAdapter);
        final String theFilePath = filePath;
        myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                TextView fileName = view.findViewById(R.id.fileName);
                //在Activity当中使用findViewById()方法貌似不一定需要由view对象来点,
                //但是如果直接使用, 在listView中获取到的值可能和想要的值不一样(会只获取第一个值, 也就是这里的Android文件夹)
                String theName = fileName.getText().toString();
                File theFile = new File(theFilePath+"/"+theName);
                if(theFile.isDirectory()){
                    System.out.println("判断为路径, 即将进入路径:            "+theFilePath+"/"+theName);
                    clickIn(theFilePath+"/"+theName);
                }else {
                    Toast toast=Toast.makeText(getApplicationContext(), "不能打开文件", Toast.LENGTH_SHORT);
                    toast.show();
                }
            }
        });
    }

    //点击监听: 返回上一级目录
    public void goBack(View view){
        String path = thePath.getText().toString();
        if (path.equals(getSdCardPath())){
            Toast toast=Toast.makeText(getApplicationContext(), "已经位于SD卡根目录", Toast.LENGTH_SHORT);
            toast.show();
        }else {
            int lastIndexOf = path.lastIndexOf("/");
            String newPath = path.substring(0,lastIndexOf);
            System.out.println("返回上一级目录:               "+newPath);
            clickIn(newPath);
        }
    }

    //判断SDCard是否存在
    public static boolean isSdCardExist() {
        return Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED);
    }

    //获取SDCard根目录
    public static String getSdCardPath() {
        boolean exist = isSdCardExist();
        String sdpath = "";
        if (exist) {
            sdpath = Environment.getExternalStorageDirectory()
                    .getAbsolutePath();
        } else {
            sdpath = "不适用";
        }
        return sdpath;
    }

    //得到一个路径下所有的文件/文件夹
    public static String[] getChilds(String pathString){
        File path = new File(pathString);
        return path.list();
    }

}