已解决:安卓8.0读取文件问题。包含intent调用文件管理器得到选定文件的路径,通过获取的文件路径得到SD卡内文本文件数据的读取方法

本文为记录毕业设计部分出现的问题,作为总结
近期在写毕业设计的时候,需要实现从安卓8.0的手机内置存储卡读取文本文件的数据内容,但在开始的时候一直抛出FileNotFoundException,显示找不到文件。
先贴出我读取文件的方法:
//---------------------------------------
        //设置打开文件监听器,调用intent打开系统文件管理得到路径
 Btnopen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("*/*");//设置类型,我这里是任意类型,任意后缀的可以这样写。
                //intent.setType(“audio/*”); //选择音频
                //intent.setType(“video/*”); //选择视频 (mp4 3gp 是android支持的视频格式)
                //intent.setType(“video/*;image/*”);//同时选择视频和图片
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                startActivityForResult(intent, 1);
            }
        });
    }

先通过intent,调用系统自带的文件管理器,选择文件。

 //回调
    //onActivityResult函数响应了选择文件的操作。
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {//是否选择,没选择就不会继续
            Uri uri = data.getData();//得到uri,后面就是将uri转化成file的过程。
            String[] proj = {MediaStore.Images.Media.DATA};

            Cursor actualimagecursor = managedQuery(uri, proj, null, null, null);
            int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            actualimagecursor.moveToFirst();
            String img_path = actualimagecursor.getString(actual_image_column_index);
            File file = new File(img_path);
            Toast.makeText(OpenFile.this, file.toString(), Toast.LENGTH_SHORT).show();
            String dd =file.toString();
            dizhi.setText(file.toString());
            readfilename=dizhi.getText().toString();
        }
}

在这里选择要打开的文件后,得到文件的路径。
我自己在华为mate8真机测试时得到的测试路径为:/storage/emulated/0/1.txt
大家自己测试的时候根据机型不同可能会有变化。

然后是读取文件:

//    读取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();
        }
        filedata=sb.toString();
        return sb.toString();
    }
}

其中

filename = Environment.getExternalStorageDirectory().getCanonicalPath() + "/" + filename;
	

这句屏蔽掉是因为,我在我自己的项目中已经得到了文件的绝对路径,不需要再通过这个filename获取文件名。

接下来是我这几天一直读取不了文件的原因:Android8.0的SD卡读取权限
其实在这之前我已经在AndroidMainfest.xml文件中添加了SD卡的读写权限:

    
    

但在Android6.0后对于读写文件还需要在.java中添加动态权限申请

 private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE" };
 try {
                //检测是否有写的权限
                int permission = ActivityCompat.checkSelfPermission(this,
                        "android.permission.WRITE_EXTERNAL_STORAGE");
                if (permission != PackageManager.PERMISSION_GRANTED) {
                    // 没有写的权限,去申请写的权限,会弹出对话框
                    ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

下面try部分放在Oncreat方法中即可

贴上java文件:

package com.test.BTClient;

import android.Manifest;
import android.app.Activity;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class OpenFile extends Activity {


    private  Button open;
    private Button Btnopen;
    private Button show;
    private TextView data;
    private EditText dizhi;

    public String readfilename;
    public String filedata;


    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE" };




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_open_file);


//        int permission = ActivityCompat.checkSelfPermission(this,
//                Manifest.permission.READ_EXTERNAL_STORAGE);
//
//        if (permission != PackageManager.PERMISSION_GRANTED) {
//            // 请求权限
//            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
//                    EXTERNAL_STORAGE_REQ_CODE);
//        }


            try {
                //检测是否有写的权限
                int permission = ActivityCompat.checkSelfPermission(this,
                        "android.permission.WRITE_EXTERNAL_STORAGE");
                if (permission != PackageManager.PERMISSION_GRANTED) {
                    // 没有写的权限,去申请写的权限,会弹出对话框
                    ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }


        open =findViewById(R.id.open);
        Btnopen = (Button) findViewById(R.id.BtnOpen);
        show = (Button) findViewById(R.id.Toshowdata);
        data = (TextView) findViewById(R.id.in);
        dizhi = (EditText) findViewById(R.id.dizhi);

        show.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent =new Intent(OpenFile.this,showdata.class);
                startActivity(intent);
            }
        });

        open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {

                    readFromSD(readfilename);
                    data.setText(filedata);

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

        //---------------------------------------
        //设置打开文件监听器,调用intent打开系统文件管理得到路径
        Btnopen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("*/*");//设置类型,我这里是任意类型,任意后缀的可以这样写。
                //intent.setType(“audio/*”); //选择音频
                //intent.setType(“video/*”); //选择视频 (mp4 3gp 是android支持的视频格式)
                //intent.setType(“video/*;image/*”);//同时选择视频和图片
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                startActivityForResult(intent, 1);
            }
        });
    }

    //回调
    //onActivityResult函数响应了选择文件的操作。
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {//是否选择,没选择就不会继续
            Uri uri = data.getData();//得到uri,后面就是将uri转化成file的过程。
            String[] proj = {MediaStore.Images.Media.DATA};

            Cursor actualimagecursor = managedQuery(uri, proj, null, null, null);
            int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            actualimagecursor.moveToFirst();
            String img_path = actualimagecursor.getString(actual_image_column_index);
            File file = new File(img_path);
            Toast.makeText(OpenFile.this, file.toString(), Toast.LENGTH_SHORT).show();
            String dd =file.toString();
            dizhi.setText(file.toString());
            readfilename=dizhi.getText().toString();
        }
        }



//
//    //read file
//    public String readFile(String filename)throws Exception{
//        FileInputStream is=context.openFileInput(filename);
//        byte b[]=new byte[1024];
//        int len=0;
//        ByteArrayOutputStream baos=new ByteArrayOutputStream();
//        //先把数据写入内存
//        while((len=is.read(b))!=-1){
//            baos.write(b,0,len);
//        }
//        //从内存中读取数据
//        byte data[]=baos.toByteArray();
//
//        baos.close();
//        is.close();
//
//        return new String(data);
//    }


//    读取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();
        }
        filedata=sb.toString();
        return sb.toString();



    }

}

在测试过程中发现
1.调用文件管理器只能一步步进入文件夹选择到的文件才是可以正常继续运行,否则活动会崩溃。
2.如果EditView内不输入内容,见单击打开,活动也会崩溃。
解决方法设想为:添加if条件判断等后续解决

你可能感兴趣的:(问题)