一.存储在内部还是外部?
AndroidManifest.xml中manifest标签下有一个属性android:installLocation
,用于指定应用程序安装在什么地方,该属性有三个可选值:
- auto:程序可能被安装在外部存储器上,例如SD卡;但是默认会被安装到手机内存中。当手机内存为空时,程序将被安装到外部存储器上;当程序安装到手机上后,用户可以决定把程序放在外部存储器还是内存中。
- internalOnly:默认值,程序只能被安装在内存中,如果内存为空,程序则不能成功被安装。
- preferExternal:将程序安装在外部存储器,但是系统不保证程序一定会被安装到外部存储器上。当外部存储器不可以安装或为空时,程序将被安装到内存中。当程序使用了forward-locking机制时也将被安装到内存中,因为外部存储不支持此机制。程序安装后,用户可以自由切换程序应该在外部还是内部存储器上。
获取External存储的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
二.openFileInput和openFileOutput
Context提供了两个方法打开应用程序的数据文件夹里的文件IO流:
- FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应的输入流。
- FileOutputStream openFileOutput(String name, int mode):打开应用程序的数据文件夹下的name文件对应的输出流。第二个参数指定打开文件的模式,该模式支持如下值:
- MODE_PRIVATE:该文件只能被当前程序读写。
- MODE_APPEND:以追加方式打开该文件,应用程序可以向该文件中追加内容。
- MODE_WORLD_READABLE:该文件的内容可以被其他程序读取。
- MODE_WORLD_WRITEABLE:该文件的内容可以由其他程序读写。
Context还提供了访问应用程序的数据文件夹的方法:
- getDir(String name, int mode):在应用程序的数据文件夹下获取或创建name对应的子目录。
- File getFileDir():获取应用程序的数据文件夹的绝对路径。
- String[] fileList():返回应用程序的数据文件夹下的全部文件。
- deleteFile(String):删除应用程序的数据文件夹下的指定文件。
核心代码如下:
public String read() { try { FileInputStream inStream = this.openFileInput("message.txt"); byte[] buffer = new byte[1024]; int hasRead = 0; StringBuilder sb = new StringBuilder(); while ((hasRead = inStream.read(buffer)) != -1) { sb.append(new String(buffer, 0, hasRead)); } inStream.close(); return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } public void write(String msg){ // 步骤1:获取输入值 if(msg == null) return; try { // 步骤2:创建一个FileOutputStream对象,MODE_APPEND追加模式 FileOutputStream fos = openFileOutput("message.txt", MODE_APPEND); // 步骤3:将获取过来的值放入文件 fos.write(msg.getBytes()); // 步骤4:关闭数据流 fos.close(); } catch (Exception e) { e.printStackTrace(); } }
openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data/<package name>/files目录,如: /data/data/cn.tony.app/files/message.txt,
三.读写SD卡上的文件
读写SD卡上文件的步骤:
- 调用Environment的getExternalStorageState()方法判断手机上是否插入了SD卡,并且应用程序具有读写SD卡的权限。使用如下代码:
//如果返回true,说明已插入SD卡,且应用程序具有读写SD卡的能力 Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
- 调用Environment的getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录。
- 使用FileInputStream、FileOutputStream、FileReader或FileWriter读写SD卡里的文件。
为了读写SD卡上的数据,必须在AndroidManifest.xml中添加读写SD卡的权限:
<!-- 在SD卡中创建于删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 向SD卡中写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
接着在使用SDcard进行读写的时候 会用到Environment类下面的几个静态方法 :
1: getDataDirectory() 获取到Android中的data数据目录(sd卡中的data文件夹)
2:getDownloadCacheDirectory() 获取到下载的缓存目录(sd卡中的download文件夹)
3:getExternalStorageDirectory() 获取到外部存储的目录 一般指SDcard(/storage/sdcard0)
4:getExternalStorageState() 获取外部设置的当前状态 一般指SDcard,比较常用的应该是 MEDIA_MOUNTED(SDcard存在并且可以进行读写)还有其他的一些状态,可以在文档中进行查找。
5:getRootDirectory() 获取到Android Root路径
以下是具体操作:
1,判断SD卡是否存在
/** * 判断SDCard是否存在 [当没有外挂SD卡时,内置ROM也被识别为存在sd卡] * * @return */ public static boolean isSdCardExist() { return Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED); }
2,获取SD卡根目录
/** * 获取SD卡根目录路径 * * @return */ public static String getSdCardPath() { boolean exist = isSdCardExist(); String sdpath = ""; if (exist) { sdpath = Environment.getExternalStorageDirectory() .getAbsolutePath(); } else { sdpath = "不适用"; } return sdpath; }
3,获取默认的文件存放路径
/** * 获取默认的文件路径 * * @return */ public static String getDefaultFilePath() { String filepath = ""; File file = new File(Environment.getExternalStorageDirectory(), "abc.txt"); if (file.exists()) { filepath = file.getAbsolutePath(); } else { filepath = "不适用"; } return filepath; }
4-1,使用FileInputStream读取文件
try { File file = new File(Environment.getExternalStorageDirectory(), "test.txt"); FileInputStream is = new FileInputStream(file); byte[] b = new byte[inputStream.available()]; is.read(b); String result = new String(b); System.out.println("读取成功:"+result); } catch (Exception e) { e.printStackTrace(); }
4-2,使用BufferReader读取文件
try { File file = new File(Environment.getExternalStorageDirectory(), DEFAULT_FILENAME); BufferedReader br = new BufferedReader(new FileReader(file)); String readline = ""; StringBuffer sb = new StringBuffer(); while ((readline = br.readLine()) != null) { System.out.println("readline:" + readline); sb.append(readline); } br.close(); System.out.println("读取成功:" + sb.toString()); } catch (Exception e) { e.printStackTrace(); }
案例代码:
// 文件写操作函数 private void write(String content) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } PrintStream out = null; // 打印流对象用于输出 try { out = new PrintStream(new FileOutputStream(file, true)); // 追加文件 out.println(content); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { out.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "保存失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } } // 文件读操作函数 private String read() { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } Scanner scan = null; // 扫描输入 StringBuilder sb = new StringBuilder(); try { scan = new Scanner(new FileInputStream(file)); // 实例化Scanner while (scan.hasNext()) { // 循环读取 sb.append(scan.next() + "\n"); // 设置文本 } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (scan != null) { scan.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "读取失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } return null; }
四.操作assets、raw、res目录下文件
1.assets
资源文件夹,在main下与res同级,与res不同的是,该目录下的资源文件在打包apk时,会按原格式一并被打包。
有三种使用方法:
- 在assets下放一个test.html文件,加载该文件:
webView.loadUrl("file:///android_asset/test.html");//假设已经创建了一个WebView实例
- 同样是读取test.html文件:
//这里的open只能打开文件,不能打开文件夹 InputStream inputStream = getResource().getAssets().open("test.html");
-
读取列表、读取图片、读音乐,assets目录下包含一个images目录和一个mp3文件xuwei.mp3,images目录中包含一张图片dog.jpg:
String[] fileNames = getAssets().list("images/");//读列表 InputStream inputStream = getAssets().open("images/dog.jpg");//读图片 Bitmap bitmap = BitmapFactory.decodeStream(inputStream); imageView.setImageBitmap(bitmap); AssetFileDescriptor assetFileDescriptor = getAssets().openFd("xuwei.mp3");//得到asset文件描述符 player.reset();//假设已创建一个MediaPlayer实例 player.setDataResource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength()); player.prepare(); player.start();
2.raw
资源文件夹,在res目录下,系统会为res目录下的所有资源生成相应的资源ID,raw中的文件也不例外,所以可以通过ID去访问res/raw目录中的任何文件,而assets目录中的文件就需要借助AssetManager去访问了。
assets目录允许下面有多级子目录,而res/raw下不允许存在目录结构。
读raw下的xuwei.mp3文件:
InputStream is = getResources().openRawResource(R.raw.xuwei);
3.res
res目录下的文件都可用getResources()方法读取。
五.SD卡文件浏览器
利用Java的File类开发一个SD卡文件浏览器,通过Environment.getExternalStorageDirectory()访问系统的SD卡目录,然后通过File的listFiles()方法获取指定目录下的全部文件和文件夹。
布局文件如下:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.trampcr.sdfileexplorer.MainActivity">
<TextView
android:id="@+id/path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center_horizontal" />
<ListView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/path" />
<Button
android:id="@+id/parent"
android:layout_width="38dp"
android:layout_height="34dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/home" />
</RelativeLayout>
布局文件包含一个TextView用于显示当前路径,ListView显示当前目录下文件和文件夹,Button用于返回上一级目录。
ListView中的子布局,包含一个ImageView和一个TextView:
line.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:id="@+id/icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/folder"/>
<TextView
android:id="@+id/file_name"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="abc"/>
</LinearLayout>
主程序代码如下:
public class MainActivity extends AppCompatActivity {
private ListView mListView;
private TextView mTextView;
//记录当前的父文件夹
private File mCurrentParent;
//记录当前路径下的所有文件的文件数组
File[] mCurrentFiles;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.list);
mTextView = (TextView) findViewById(R.id.path);
//获取系统的SD卡的目录
File root = new File(String.valueOf(Environment.getExternalStorageDirectory()));
//如果SD卡存在
if (root.exists()){
mCurrentParent = root;
mCurrentFiles = root.listFiles();
//使用当前目录下的全部文件、文件夹来填充ListView
inflateListView(mCurrentFiles);
}
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mCurrentFiles[position].isFile()){
return;
}
File[] tmp = mCurrentFiles[position].listFiles();
if (tmp == null || tmp.length == 0){
Toast.makeText(MainActivity.this, "当前路径不可访问或该路径下没有文件", Toast.LENGTH_SHORT).show();
}else {
mCurrentParent = mCurrentFiles[position];
mCurrentFiles = tmp;
inflateListView(mCurrentFiles);
}
}
});
//获取上一级目录的按钮
Button parent = (Button) findViewById(R.id.parent);
parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if (!mCurrentParent.getCanonicalFile().equals("/mnt/shell/emulated/0")){
mCurrentParent = mCurrentParent.getParentFile();
mCurrentFiles = mCurrentParent.listFiles();
inflateListView(mCurrentFiles);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
private void inflateListView(File[] files) {
//创建一个List集合,List集合的元素是Map
List<Map<String, Object>> listItems = new ArrayList<>();
for (int i = 0; i < files.length; i++) {
Map<String, Object> listItem = new HashMap<>();
if (files[i].isDirectory()){
listItem.put("icon", R.drawable.folder);
}else {
listItem.put("icon", R.drawable.file);
}
listItem.put("fileName", files[i].getName());
listItems.add(listItem);
}
//创建一个SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.line, new String[]{"icon", "fileName"}, new int[]{R.id.icon, R.id.file_name});
mListView.setAdapter(simpleAdapter);
try {
mTextView.setText("当前路径为:" + mCurrentParent.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用File[]数组填充ListView,填充是程序会根据File[]数组里的数据元素代表的是文件还是文件夹来选择使用文件图标或文件夹图标。
运行上面程序,可以看到:
相关推荐
**Android数据存储之FileProvider详解** 在Android应用开发中,数据存储是一个不可或缺的部分。FileProvider是一种特殊类型的ContentProvider,它允许应用程序安全地分享私有文件,如图片、视频或其他二进制数据,...
在Android应用开发中,本地数据存储是至关重要的一个环节,特别是在处理用户数据或者应用程序需要持久化数据时。本文将深入探讨Android系统中的文件存储机制,包括如何读取、写入、重写和删除.txt格式的文件。理解...
Android提供了多种数据存储方式,其中包括使用File类进行文件存储。本教程将深入探讨如何在Android中利用File类进行数据操作,包括创建、读取、修改和删除文件,以及文件路径的处理。 1. **基本概念** - **File类*...
"Android存储字符串数据到txt文件" Android存储字符串数据到txt文件是Android开发中的一种常见需求,对于大多数开发者来说,存储字符串数据到txt文件是一种非常有用的功能。今天,我们将详细介绍如何在Android中...
在Android系统中,数据存储是应用开发者必须掌握的重要技能之一,因为这关乎到应用程序如何持久化数据,确保用户数据在程序关闭或设备重启后依然可访问。本篇将重点讨论Android内置SD卡(通常称为内部存储)的数据...
6. **文件存储**:通过File类,开发者可以直接读写文件,适用于存储任意格式的数据,如日志文件、配置文件等。 7. ** Parcelables与Serializable**:当需要在Intent中传递复杂对象或在进程间通信时,可以使用...
本文将详细介绍Android中的四种主要数据存储方式:SharedPreferences、File、SQLite数据库以及网络存储。 1. SharedPreferences: SharedPreferences是Android提供的一种轻量级的数据存储方式,适合存储用户偏好...
本资源“Android学习之数据存储”提供了一些关于Android数据存储的源码,这对于理解Android数据存储机制及其实践应用非常有帮助。 在Android中,有多种方式来实现数据存储,包括: 1. **SharedPreferences**:这是...
本文将深入探讨“android 数据存储之 Files”,重点关注如何使用`java.io.File`类在Android设备上进行文件存储。`Files`通常指的是通过创建和操作文件来存储数据的方式,这是Android提供的一种简单而直接的数据持久...
本资料包“Android学习之数据存储.zip”提供了一些关于Android数据存储的源码,是学习和参考的理想资源。下面将详细探讨Android中的几种数据存储方式及其应用场景。 1. **Shared Preferences** Shared Preferences...
首先,Android提供了多种数据存储方式,包括内部存储、外部存储(如SDCard)、SQLite数据库、SharedPreferences以及文件系统。其中,SDCard主要用于存储大容量的数据,如媒体文件、应用备份等。使用SDCard的优点在于...
总结起来,Android在Sdcard上的数据存储涉及权限管理、路径操作以及文件I/O操作。在实际应用中,开发者应根据需求选择合适的存储方式,并确保遵循最新的Android存储策略,以保证应用的兼容性和安全性。
Android系统提供了多种方式来存储应用程序的数据,包括私有储存和外部储存。本文将深入探讨如何在Android 6.0及以上版本中读写私有储存文件和外部储存文件,并适配新的权限管理机制。 首先,私有储存是每个应用程序...
在Android开发中,数据存储是不可或缺的一部分,它用于持久化应用程序的数据,以便在用户退出或设备重启后仍能保持数据。本资源“android数据存储集锦源码”提供了一个全面的示例,帮助开发者深入了解和实践Android...
实验10-Android数据存储与IO是Android平台开发与应用课程的一个重要实验,旨在让学生掌握Android中多种数据存储的方法,包括SharedPreferences、File以及SQLite数据库。实验涵盖了读写其他应用程序的...
在Android应用开发中,数据存储是一项基础且重要的任务。这篇自学笔记主要涵盖了三种常见的数据存储方式:文件存储、SharedPreferences以及获取SD卡信息。下面将详细解释这些知识点。 **1. 文件存储** Android提供...
本篇文章将重点探讨“安卓数据存储之文件存储”,包括内部存储和外部存储两种主要形式。 1. **内部存储** - 内部存储是Android为每个应用程序提供的私有存储空间,只有该应用有权访问。数据存储在这里是安全的,...
在Android开发中,数据存储是不可或缺的一部分,它用于持久化应用程序的数据,以便在用户退出或设备重启后仍能保留这些信息。Android提供了五种主要的数据存储方式:共享首选项(SharedPreferences)、内部存储...
本压缩包文件"安卓Android源码——安卓Android学习——数据存储.rar"显然是针对安卓数据存储机制的学习资料,其中可能包含了相关的源代码示例和讲解。下面我们将深入探讨安卓中的数据存储方法。 1. **Shared ...
再者,文件存储也是Android中常见的数据存储方式。可以通过File类或者ParcelFileDescriptor进行操作,适用于存储较大文本、图片或者其他二进制数据。根据需求,可以选择内部存储(私有且不易被其他应用访问)或外部...