Android 文件读写

这篇具有很好参考价值的文章主要介绍了Android 文件读写。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Android的App可以读写的位置为:
一、内置data目录下对应app名称的目录;
二、扩展SD卡(包括虚拟的内置SD卡和外置SD卡);

一、先说说内置data目录下文件的读写。

内置data目录即内部存储,指的是应用内部独有的存储,这部分存储的文件、数据,只能被应用自身访问到,其他应用都没有权限访问。

一般情况下,/data开头的路径都是内部存储。而一般应用所能够访问到的就是下面几个路径,称为应用内部私有存储。

应用内部私有存储:
/data/user/0/<包名>
/data/user/0/<包名>/files #存放文件数据
/data/user/0/<包名>/databases #存放Sqlite的数据库文件
/data/user/0/<包名>/shared_prefs #存放SharedPreference的数据
/data/user/0/<包名>/cache #存放缓存文件

一旦App被卸载,系统将会移除内部存储中相关应用的数据。

方式1:内置API读写

这个位置的读写有提供一套单独的API来读写,无需申明特殊权限。

代码中有个openFileInput的方法,这个方法是Android内置的,需放在Activity中才能执行。

如下:


    //读取内置data目录下文件
    public String readDataFile(String fileName) {
        String res = "";
        try {
            FileInputStream fin = openFileInput(fileName);
            int length = fin.available();
            byte[] buffer = new byte[length];
            fin.read(buffer);
            res = new String(buffer);
            fin.close();

        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Exception", "readDataFile Error!" + e.getMessage());
        }
        return res;
    }

    //写入内置data目录下文件
    private void writeDataFile(String fileName, String content) {
        try {
            FileOutputStream fut = openFileOutput(fileName, Context.MODE_PRIVATE | Context.MODE_APPEND);
            byte[] bytes = content.getBytes();
            fut.write(bytes);
            fut.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Exception", "writeDataFile Error!" + e.getMessage());
        }
    }

测试代码:

String fileName="test.txt";
writeDataFile(fileName, "Hello Android");
String txt = readDataFile(fileName);
Log.e("txt", txt);

方式2:获取对应的data路径后,通过普通的方法读写data中的文件。

手动获取拼接data目录下文件路径,然后用通用的文件读写方式进行读写。

 通用读写文件的辅助类,FileHelper.java

package com.rc114.scanner;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URLDecoder;

public class FileHelper {
    public static String combinePath(String path1, String path2) {
        File file1 = new File(path1);
        File file2 = new File(file1, path2);
        return file2.getPath();
    }

    /**
     * 读取文件
     *
     * @param filepath 文件路径
     */
    public static String readFile(String filepath) {
        String encoding = "UTF-8";
        return readFile(filepath, encoding);
    }

    /**
     * 读取文件,指定编码
     *
     * @param filepath 文件路径
     */
    public static String readFile(String filepath, String encoding) {
        try {
            filepath = URLDecoder.decode(filepath, "utf-8");
            File file = new File(filepath);
            Long filelength = file.length();
            byte[] filecontent = new byte[filelength.intValue()];
            FileInputStream in = new FileInputStream(file);
            in.read(filecontent);
            in.close();
            return new String(filecontent, encoding);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 将字符串写入文件
     *
     * @param filepath
     * @param text
     * @param isAppend
     */
    public static void writeFile(String filepath, String text, boolean isAppend) {

        try {
            filepath = URLDecoder.decode(filepath, "utf-8");
            File file = new File(filepath);
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            if (!file.exists()) {
                file.createNewFile();
            }

            FileOutputStream f = new FileOutputStream(filepath, isAppend);
            f.write(text.getBytes());
            f.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void writeFile(String filepath, String text, String encodeing) {

        try {
            filepath = URLDecoder.decode(filepath, "utf-8");
            File file = new File(filepath);
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            if (!file.exists()) {
                file.createNewFile();
            }

            // FileOutputStream f = new FileOutputStream(filepath, "GBK");
            // f.write(text.getBytes());
            // f.close();

            OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(filepath), encodeing);
            writer.append(text);
            writer.close();

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

}

测试代码:

//获取data目录下对应包名根目录
String dataDir = Environment.getDataDirectory().getPath() + "/data/" + packageName;

//拼接待读写文件路径
String filepath = FileHelper.combinePath(dataDir, "test.txt");

//写入文件
FileHelper.writeFile(filepath, "Hello", "utf-8");

//读取文件
String txt = FileHelper.readFile(filepath);

Log.e("txt", txt);

二、扩展SD卡文件读写

扩展SD卡文件即外部存储,指的是是公共的存储,这部分存储理论上是全局可见的,所有的应用都可以访问这部分数据,一般情况下,路径都是以/storage开头的,比如说/storage/emulated/0就是属于外部存储,这个路径的实际的挂载点是/data/media。又比如外置sdcard的路径为/storage/13FC-0F0B。 相比较内部存储一定会存在,外部存储可能是sdcard或者通过otg挂载的U盘形式,所以可能出现没有挂载的情况,所以所有的外部存储要在使用前通过下面的方式判断是否有被挂载。

    /*检查外部存储是否可写*/
    public boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            return true;
        }
        return false;
    }

    /*检查外部存储是否可读*/
    public boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state) ||
                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            return true;
        }
        return false;
    }

访问外部存储需在AndroidManifest.xml文件中申明权限:

<!-- 存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" tools:ignore="ProtectedPermissions" />

安卓6.0以后,谷歌要求危险权限必须动态获取,所以还要使用requestPermissions在运行时获取权限。

  private static String[] PERMISSIONS_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    private static int REQUEST_PERMISSION_CODE = 100;

    //获取权限
    private void getPermission() {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_PERMISSION_CODE);
            } else {

                boolean writable = isExternalStorageWritable();
                boolean readable = isExternalStorageReadable();
                Log.e("外部存储读写", "写:" + writable + "-读:" + readable);

                File root = Environment.getExternalStorageDirectory();//取得外部存储根路径
                File[] files = root.listFiles();
                if (files != null) {
                    for (int i = 0; i < files.length; i++) {
                        if (files[i].isDirectory()) {
                            Log.e("文件夹", files[i].toString());
                        }
                    }
                }

            }
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSION_CODE) {
            for (int i = 0; i < permissions.length; i++) {
                Log.i("MainActivity", "申请的权限为:" + permissions[i] + ",申请结果:" + grantResults[i]);
            }
        }
    }

 在Activity的onCreate事件中执行getPermission()方法,动态获取存储权限。

完成了上面的操作后,在代码:

File root = Environment.getExternalStorageDirectory();//取得外部存储根路径
File[] files = root.listFiles();

中,root.listFiles()可能会返回null,还是无法读取或写入文件。

查了下资料,Android 10 或更高版本,还需要做一个配置:在AndroidManifest.xml中,还需增加:android:requestLegacyExternalStorage="true"

android 读取文件,Android,android,java,开发语言

 利用上面的FileHelper.java类,测试写入一个文件:

File root = Environment.getExternalStorageDirectory();
FileHelper.writeFile(FileHelper.combinePath(root.getPath(), "text.txt"), "Hello", false);

测试遍历根目录:

File root = Environment.getExternalStorageDirectory();
File[] files = root.listFiles();
if (files != null) {
	for (int i = 0; i < files.length; i++) {
		if (files[i].isDirectory()) {
			Log.e("文件夹", files[i].toString());
		}
		if (files[i].isFile()) {
			Log.e("文件", files[i].toString());
		}
	}
}

输出结果:

android 读取文件,Android,android,java,开发语言

至此,完成了外部存储的读写功能。 

2023-9-20 14:07:56 补充

Android 13(Api Level 33)将READ_EXTERNAL_STORAGE进一步细分成为了:

读取图片的:READ_MEDIA_IMAGE、

读取视频的:READ_MEDIA_VIDEO、

读取音频的:READ_MEDIA_AUDIO

所以如果要适配Android 13,还需做以下处理:

在AndroidManifest.xml中增加申明:

<!--  一般来说,允许用户自定义头像的app都需要这个权限  -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"
    android:minSdkVersion = "33"/>
<!--  如果你想开发音乐播放器之类需要获取音频的app,加上这个权限  -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"
    android:minSdkVersion = "33"/>
<!--  如果你想开发视频编辑器之类需要获取视频的app,加上这个权限  -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"
    android:minSdkVersion = "33"/>
<!--  向前兼容  -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />

动态申请权限做相应的修改:

public static final String READ_MEDIA_AUDIO = "android.permission.READ_MEDIA_AUDIO";
public static final String READ_MEDIA_IMAGES = "android.permission.READ_MEDIA_IMAGES";
public static final String READ_MEDIA_VIDEO = "android.permission.READ_MEDIA_VIDEO";


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
   ActivityCompat.requestPermissions( activity,new String[]{
           READ_MEDIA_IMAGES,
           READ_MEDIA_AUDIO,
           READ_MEDIA_VIDEO
   },MEDIA_READ_REQUEST_CODE);
}else{
   ActivityCompat.requestPermissions( activity,new String[]{
           READ_EXTERNAL_STORAGE
   },MEDIA_READ_REQUEST_CODE);
}
 

参考资料:

​​​​​​1.Android中的内部存储和外部存储_build hero的博客-CSDN博客_android 外部存储

2.android - Environment.getExternalStorageDirectory() deprecation alternatives - Stack Overflow

3.Android 13媒体文件访问权限适配_闲暇部落的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-796456.html

到了这里,关于Android 文件读写的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 安卓开发语言kotlin与Java该如何选择

            如今在Android开发中,应用层开发语言主要是Java和Kotlin,Kotlin是后来加入的,主导的语言还是Java。kotlin的加入仿佛让会kotlin语言的开发者更屌一些,其实不然。         有人说kotlin的引入是解决开发者复杂的逻辑,并且对空指针控制的比较友好,但是我们在开

    2024年02月11日
    浏览(66)
  • 【Android】Frida Hook 文件读写操作

    在挖掘客户端漏洞的时候,通常会关注应用对什么文件进行了读写操作,当我们能控制被读的文件或观测到敏感写入的文件,通常可以造成一定危害。本文详细介绍了如何通过frida监控文件读写操作。 在Linux系统下,文件的创建、读取、追加、写入和删除等操作涉及到以下系

    2024年02月08日
    浏览(178)
  • Android11及以上 文件读写权限申请

    Android11 读写权限申请 Android11系统对应用写入权限做了严格的限制。本文介绍如何获取文件读写权限。项目中 build.gradle 的 targetSdkVersion = 29 ,会出现读写问题。 当 targetSdkVersion = 29,通过设置requestLegacyExternalStorage=“true”,还能解决。 当 targetSdkVersion = 30后,需要申请所有文件

    2023年04月10日
    浏览(60)
  • android 11后文件读写访问权限申请

    android 11后对文件读写访问权限管理 与 android 10又有了新的要求,导致在读写或者访问时出现error:java.io.FileNotFoundException: /storage/emulated/0/file_path open failed: EACCES (Permission denied),以下为android 11文件管理权限申请办法 回忆android 10 文件访问权限申请 step 1: AndroidManifest中添加权限申

    2024年02月05日
    浏览(47)
  • Android 保存/读取本地SD卡文件(兼容Android 13)

    1.manifeast文件 (1)app权限 (2)application配置 (3)组件配置 注意:Android 12以上,组件创建会自动生成以下属性 表示”是否支持其它应用调用当前组件” 如果不添加改属性,会报错。 2.动态申请文件存储权限 说明,Android的权限根据版本号分为三种 1:Android6.0之前 2:Androi

    2024年02月05日
    浏览(64)
  • Android 读取Txt文件内容

    View Code 一个获取InputStream中字符串内容的方法:传入一个InputStream,返回其中的文本内容。 View Code 以gbk编码读取内容,不同的文本文件可能编码不同,如果出现乱码,可能需要调整编码。 手机测试有安卓版本限制、生产厂家限制,如:某OS

    2024年02月17日
    浏览(45)
  • Android开发 拍照+读取相册+保存到本地

    注册除了MainActivity的其他两个界面Albums和Camera,添加provider,申请使用相机的权限,读写权限 file_path.xml代码 如果虚拟机可以运行,手机不能安装,gradle.properties里面添加 文件结构 总结 https://wwzb.lanzoue.com/imUKH0n1nq4d 密码:1eda 分享Demo可试试效果 参考来源:  Android studio调用手机

    2024年02月05日
    浏览(62)
  • Android 11 上的文件读写权限(MANAGE_EXTERNAL_STORAGE)

         Android11 + RK3566 + AndroidStudio Android 权限的变化, 几乎每个版本的SDK都会有, 其中最大的一次是在6.0时, 增加的动态权限申请 读写存储的权限也几经更迭, 对开发人员来说, 越来越难.比如, 本文所要讨论的: 允许管理所有文件 首先是 targetSdkVersion 大于等于 30. (build.gradle) 当声

    2024年01月16日
    浏览(43)
  • android studio 添加并读取json配置文件

    第一步:在android  studio中添加json文件;   第二步:读取文件的函数

    2024年02月16日
    浏览(46)
  • UniApp写入读取android本地文件,不会被清除

           项目背景,我们是用uniapp编写的收银程序,然后打包到android工程,再打包成apk包安装到用户的收银机上,收银机是android系统。由于项目需求,每次升级我们收银系统版本后,之前连接的打印机和LED显示屏的缓存数据都会被重新清除,因为升级相当于重新安装apk。所以

    2024年02月13日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包