您的位置:首页 > 移动开发 > Android开发

Android文件读写操作

2015-06-08 15:54 423 查看
一、概要

本节主要介绍android几种文件的读写方式,主要包括资源文件、内部存储区文件、外部存储区文件。

1、资源文件:

apk中有两种资源文件,raw下的和assets下的,这些数据只能读取,不能写入。更重要的是该目录下的文件大小不能超过1M。

2、内部存储:

总是可用的

这里的文件默认是只能被你的app所访问的。

当用户卸载你的app的时候,系统会把internal里面的相关文件都清除干净。

Internal是在你想确保不被用户与其他app所访问的最佳存储区域。

3、 外部存储:

并不总是可用的,因为用户可以选择把这部分作为USB存储模式,这样就不可以访问了。

是大家都可以访问的,因此保存到这里的文件是失去访问控制权限的。

当用户卸载你的app时,系统仅仅会删除external根目录(getExternalFilesDir())下的相关文件。

External是在你不需要严格的访问权限并且你希望这些文件能够被其他app所共享或者是允许用户通过电脑访问时的最佳存储区域。

二、读写方式
1.资源文件(只读)



*res/raw和assets的相同点:

(1)两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。

*res/raw和assets的不同点:

(1)res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。

(2)res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹。
(3)读取方式

raw使用InputStreamin = getResources().openRawResource(R.raw.test);
asset使用InputStreamin = getResources().getAssets().open(fileName);

注:在使用InputStream的时候会抛出IOException,需在函数头部加上throws IOException或在使用时用try
catch语句捕获


raw资源文件读取:

/**
	 * 读取raw资源文件下的文件
	 * @throws IOException 
	 */
	private void getRawResource() {

		String result="";
		try {
			//得到资源中的Raw数据流
			InputStream in = getResources().openRawResource(R.raw.test); 

			//得到数据的大小
			int length = in.available();  
			//文件大小的byte数组
			byte [] buffer = new byte[length];        
			//读取数据到byte数组
			in.read(buffer);         
			//转成string格式,依test.txt的编码类型选择合适的编码,如果不调整会乱码 
			result = EncodingUtils.getString(buffer, "GBK"); 

			//关闭 流   
			in.close();
			Log.i("TAG", "rawResource:"+result);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}     
	}




assets资源文件读取:



/**
	 * 读取assets资源文件下的文件
	 * @param fileName 文件名
	 */
	private void getAssertResource(String fileName) {
		String res="";
		try {
			// \Test\assets\filename这里有这样的文件存在
			InputStream in = getResources().getAssets().open(fileName);

			int length = in.available();         
			byte [] buffer = new byte[length]; 
			in.read(buffer);
			res = EncodingUtils.getString(buffer, "GBK");
			Log.i("TAG", "assertResource:"+res);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}            
	}


2.内部存储区文件(/data/data/<应用程序名>目录上的文件)

(1)存储区

方式一(openFileOutput):

<1>写操作:FileOutputStream fout =openFileOutput(fileName, MODE_PRIVATE);

<2>读操作:FileInputStream fin = openFileInput(fileName);

<3>写操作中的使用模式:

MODE_APPEND:即向文件尾写入数据

MODE_PRIVATE:即仅打开文件可写入数据

MODE_WORLD_READABLE:所有程序均可读该文件数据

MODE_WORLD_WRITABLE:即所有程序均可写入数据。

数据区写入:

/**
	 * 往/data/data/<应用程序名>目录上写入文件
	 */
	public void writeFile(String fileName,String writestr) {
		try {
			/*创建带文件名和操作模式的文件输出流
			 * MODE_APPEND:即向文件尾写入数据
	           MODE_PRIVATE:即仅打开文件可写入数据
	           MODE_WORLD_READABLE:所有程序均可读该文件数据
	           MODE_WORLD_WRITABLE:即所有程序均可写入数据。
			 */
			FileOutputStream fout =openFileOutput(fileName, MODE_PRIVATE);
            //获得文件大小
			byte [] bytes = writestr.getBytes();
			//写入
			fout.write(bytes);
			//关闭流
			fout.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


数据区读取:

/**
	 * 从/data/data/<应用程序名>目录/files 上读取文件
	 */
	public String readFile(String fileName){
		  String res="";
		  try{
		         FileInputStream fin = openFileInput(fileName);
		         int length = fin.available();
		         byte [] buffer = new byte[length];
		         fin.read(buffer);    
		         res = EncodingUtils.getString(buffer, "UTF-8");
		         fin.close();    
		     }
		     catch(Exception e){
		         e.printStackTrace();
		     }
		     return res;
		}

方式二(getFileDir()):

<span style="font-size:18px;"><span style="font-weight: bold;"></span></span><pre name="code" class="java">public void writeFile1(String fileName,String writestr)
File file1 = new File(getFilesDir(),fileName);

Log.d("TAG", "file1=" + file1.getAbsolutePath()); try { OutputStream outputStream1 = new FileOutputStream(file1); outputStream1.write(writestr.getBytes());

outputStream1.close(); } catch (Exception e) { e.printStackTrace(); }



以上方法在需要的地方调用即可,方法二和方法一实现的效果一样,读取方法与前面类似,已略。。

(2)缓存区

getCacheDir() 通过此方法可以获取到你的APP内部存储的文件,路径为/data/data/package_name/cache。

public void writeCache(String fileName,String writestr) {
File file2 = new File(getCacheDir(), fileName);
        Log.d("TAG", "file2=" + file2.getAbsolutePath());
        try {
            OutputStream outputStream1 = new FileOutputStream(file2);
            outputStream1.write(writestr.getBytes());
            outputStream1.close();
        } catch (Exception e) {
            e.printStackTrace();
        } }



此方法,程序调用时传入的fileName为“cache.txt”,writestr内容为“cache”,内部存储存储位置如下图所示



内部存储在你的APP卸载的时候,会一块被删除,因此,我们可以在cache目录里面放置我们的图片缓存,而且cache与files的差别在于,如果手机的内部存储控件不够了,会自行选择cache目录进行删除,因此,不要把重要的文件放在cache文件里面,可以放置在files里面,因为这个文件只有在APP被卸载的时候才会被删除。还有要注意的一点是,如果应用程序是更新操作,内部存储不会被删除,区别于被用户手动卸载。

3.外部存储区域文件

(1)外部公共区域

<1>读操作

FileInputStream fin = new FileInputStream(fileName);

<2>写操作

FileOutputStream fout = new FileOutputStream(fileName);

<3>必要步骤

①获取权限

A 获取文件修改权限

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

B可写权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

②检查内存状态(是否安装sd卡)

if(Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED))

③读写操作

SD卡写入数据:

/**
	 * 向SD卡写入文件
	 * @param fileName 文件名
	 * @param write_str 要写入的字符串
	 * @throws IOException
	 */
	public void writeFileSdcardFile(String fileName,String write_str) { 
		try{ 
			/**路径设为sdcard/fileDemo,
			 * Environment.getExternalStorageDirectory()方法获取内存卡地址
			 */
			File dir=new File(Environment.getExternalStorageDirectory()+"/fileDemo");
			if (!dir.exists())
				dir.mkdirs();
			File file=new File(dir, fileName);
			//创建带文件名的文件输出流
			FileOutputStream fout = new FileOutputStream(file); 
			//获得大小
			byte [] bytes = write_str.getBytes(); 
			//写入
			fout.write(bytes); 
			//关闭流
			fout.close(); 
		}

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


SD卡读取数据:

/**
	 * 读sd取卡中的文件
	 * @param fileName 文件名
	 * @return 文件中的内容
	 * @throws IOException
	 */
	public String readFileSdcardFile(String fileName){ 
		String res=""; 
		try{ 
			File dir=new File(Environment.getExternalStorageDirectory()+"/fileDemo");
			File file=new File(dir, fileName);
			//文件输入流
			FileInputStream fin = new FileInputStream(file);
			//获得文件大小
			int length = fin.available(); 
			//文件大小的byte数组
			byte [] buffer = new byte[length]; 
			//将文件内容读入byte数组
			fin.read(buffer);     
			//转成字符串格式
			res = EncodingUtils.getString(buffer, "UTF-8"); 
			Log.i("TAG", "读sd卡文件:"+res);
			//关闭流
			fin.close();     
		} 
		catch(Exception e){ 
			e.printStackTrace(); 
		} 
		return res; 
	}


以上文件存储在sdcard中fileDemo文件夹下

注意:关于sdcard,访问SDCard必须在AndroidManifest.xml中加入访问SDCard的权限
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File sdCardDir =Environment.getExternalStorageDirectory();//获取SDCard目录
File saveFile = new File(sdCardDir,“a.txt”);
FileOutputStream outStream = newFileOutputStream(saveFile);
outStream.write(“test”.getBytes());
outStream.close();
}

Environment.getExternalStorageState()方法用于获取SDCard的状态,如果手机装有SDCard,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED。

Environment.getExternalStorageDirectory()方法用于获取SDCard的目录。

另外,可以使用 getExternalStoragePublicDirectory() 来存储可以共享的文件,getExternalStoragePublicDirectory()在运行的时候,会需要你带有一个特定的参数来指定这些public的文件类型,以便于与其他public文件进行分类。参数类型包括DIRECTORY_MUSIC
或者 DIRECTORY_PICTURES. 如下:

public File getAlbumStorageDir(Context context, String albumName) {
    // Get the directory for the app's private pictures directory.
    File file = new File(context.getExternalFilesDir(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}


(2)外部私有存储

从上面内部存储的介绍来看,内部存储的文件应该属于私有文件,别的APP想要访问是比较困难的,那么外部存储呢?外部存储由于容量较大,一般是我们的APP保存较大文件的不二选择,那么是不是外部存储里面的文件,所有的APP都可以随意访问呢?显然并不是这样的,在外部存储中,也存在着私有文件的概念。

就像我们在前面获取内部存储方法一样,我们使用Context.getExternalCacheDir()和Context.getExternalFilesDir()就可以获取到外部存储的私有文件,我们以下面的代码为例
File file3 = new File(getExternalCacheDir().getAbsolutePath(), "getExternalCacheDir.txt");
        try {
            OutputStream outputStream1 = new FileOutputStream(file3);
            outputStream1.write("getExternalCacheDir".getBytes());
            outputStream1.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        Log.d("TAG", "file3=" + file3);

        File file4 = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "getExternalFilesDir.txt");
        try {
            OutputStream outputStream1 = new FileOutputStream(file4);
            outputStream1.write("getExternalFilesDir".getBytes());
            outputStream1.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
系统中外部私有存储位置如下图所示:


最后,不管你是使用 getExternalStoragePublicDirectory() 来存储可以共享的文件,还是使用 getExternalFilesDir() 来储存那些对与你的app来说是私有的文件,有一点很重要,那就是你要使用那些类似DIRECTORY_PICTURES
的API的常量。那些目录类型参数可以确保那些文件被系统正确的对待。例如,那些以DIRECTORY_RINGTONES 类型保存的文件就会被系统的media scanner认为是ringtone而不是音乐。

下面就是这些参数对应的文件夹




本文参考http://blog.csdn.net/zhaokaiqiang1992
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: