Android开发技术之文件的简单存储—小白篇(二)

        近期忙于一个市级赛项,由于比赛需要,所以这两天对 android 的文件存储进行了一个初步了解。现贴上这两天的学习内容,供新手小白参考,若有不懂或迷惑的地方,可联系本人 QQ 1101326120

一:手机内部存储空间文件的读取;

        1.使用该种方式存储文件,首先要获取本应用程序的数据文件夹,android为我们提供了openFileOutput(String name,int mode)和openFileInput(String name)来获取。查看帮助文档可见

         其中openFileOutput(String name,int mode)的返回类型为FileOutputStream,即使用该方法创建一个文件输出流,用来向文件中写入数据。其中第一个参数String为文件名,第二个int型参数mode有以下四个值:

        Context.MODE_PRIVATE:                                          默认模式,表示私有数据;

        Context.MODE_APPEND:                                         检查文件是否存在,如果存在会往文件追加内容,否则创建文件再写入;

        Context.MODE_WORLD_READABLE:                   当前文件可以被其他应用读取;

        Context.MODE_WORLD_WRITEABLE:                 当前文件可以被其他文件写入。

以上四个值,除了MODE_APPEND会将内容追加到文件末尾,其他的都会覆盖掉原文件内容。如果需要使用多个值可以这样使用:Context.MODE_PRIVATE+Context.MODE_APPEND;

        openFileInput(String name)的返回类型为FileInputStream,即使用该方法创建一个文件输入流,用来读取数据。其中参数String为需要读取的文件名,FileOutputStream和FileInputStream为java API中IO包里面的一个类,其中有这样一段注释:

         也就是说这个类用于处理字节流的文件有较好的性能,却也不是不可以用来处理字符,下面是用该类中的方法来处理字符的代码:

         方法一:

protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
		save=(TextView)findViewById(R.id.save);
		open=(TextView)findViewById(R.id.open);
		edit=(EditText)findViewById(R.id.edit);
		edit2=(EditText)findViewById(R.id.edit2);
		
		save.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				write(edit.getText().toString());
				edit.setText("");
				Toast.makeText(getApplicationContext(), "写入成功!", Toast.LENGTH_SHORT).show();
			}
		});
		
		open.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				edit2.setText(read());
			}
		});
	}
	
	public void write(String content){                               //传入String
					FileOutputStream output;
					try {
						output = openFileOutput("aaa",Context.MODE_WORLD_READABLE);       //用可读模式创建文件
						byte[] by=content.getBytes();       //因为FileOutputStream用来处理字节,所以要将传入的String转换为字节型          
						output.write(by);                   //向文件里面写入数据
						output.flush();                     //刷新文件流
						output.close();                     //关闭流释放资源
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
	}
	
	public String read(){
		FileInputStream input = null;
		String str ="";
		       try {
						input = openFileInput("aaa");                          //从指定文件获得字节
						/*使用下边注释中的代码时无法完整读取数据
                                                 *还会有乱码现象发生
                                                 *估计是读取过程中发生了阻塞*/
                                                //int lenth=input.toString().length();    //因为在使用read方法时需要指定字节的长度,所以我们提前获取数据的长度
						//byte[] by=new byte[lenth];              //字节大小为数据的长度
			                        int lenth=input.available();              //该方法专门用来处理上述问题
                                                input.read(lenth);                         //和上面write方法一样,用来处理字节
			                        str=new String(by,"UTF-8"); //因为最终给文本设置的类型为string型,所以我们还需要通过utf-8编码将by转换为字符型
			                        input.close();                          //关闭流释放内存
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
		return str;                                                //该返回的str即转型后的by
		}
        以上操作结果可以在设备内存date/date/包名/file/文件夹中查看,若是真机调试,必须要有root权限。

       前文中已经提到过FileOutputStream和FileInputStream用于处理字节,所以如果要较好地处理字符数据就得要将字节转换为字符类型,正好java api提供为我们提供了InputStreamReaderOutputStreamWriter用于处理该类问题,查看api可见:

代码如下:

方法二:

public void write(String content){                               //传入String
		try {
			FileOutputStream output = openFileOutput("aaa",Context.MODE_WORLD_READABLE);    //用可读模式创建文件(字节流)
			BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(output,"UTF-8"));       //该处先将字符数据添加缓存功能后再存入字节流
                        writer.write(content);                                           //写入数据
                        writer.flush();
                        writer.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public String read(){
		String str ="";
	        try {
		    String string=null;
	            FileInputStream input = openFileInput("aaa");                                 //从指定文件获得字节
	            BufferedReader buffer=new BufferedReader(new InputStreamReader(input,"UTF-8"));       //将字节流转换为字符流并为其添加缓存功能
                 
		    while((string=buffer.readLine())!=null){                  //判断读取数据是否为空,若不判断程序就无法处理,会报错闪退
		    	String ch=buffer.readLine();                            //或许readLine是该类中最有用的一个方法,事实证明确实如此
	                str=new String(ch);
	                buffer.close();	
		    }
		}catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return str;                                                //该返回的str即转型后的by
	}

         上述方法是将字节流和字符流互相转换后进行数据读取,并为其添加了缓存功能,当然如果不用缓存功能也可以,将它们进行转换后直接进行读取。另外,java API中还为我们提供了一些方法可以达到类似效果,我们可以使用字节缓冲类BufferedOutputStream和BufferedInputStream实现缓冲功能,具体功能,api注释可见:

根据本人理解,缓存功能其实是先将数据装进一个数组,然后每次对数组内的数据进行修改,直到最后确定保存时才将数据写入文件,避免了对内存文件的频繁调用,以下为实现代码:

方法三:

public void write(String content){                               //传入String
		try {
			FileOutputStream output = openFileOutput("aaa",Context.MODE_WORLD_READABLE);
			BufferedOutputStream buffer=new BufferedOutputStream(output);              //为其实现缓冲功能
			byte[] by=content.getBytes();
			buffer.write(by);                       //write返回类型为void
			buffer.flush();
			buffer.close();
			}catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
			        e.printStackTrace();
			}catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
		}
	}
	
	public String read(){
		String str = null;
		try {
		      FileInputStream input = openFileInput("aaa");
		      BufferedInputStream buffer=new BufferedInputStream(input);
		      byte[] by=new byte[buffer.available()];
		      input.read(by);            //参考api可见read返回类型为int,所以要获取字节长度
		      str=new String(by);
		      input.close();
		}catch (FileNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		}catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	       }
	return str;                                                //该返回的str即转型后的by
        }

其实我刚开始的想法是用API提供的FileReaderFileWriter中的方法来进行对手机内部存储文件的读取,或许有很多朋友和我这种想法一样。后来我试了很多次都无法实现这种效果,总结原因如下:

    1.android提供用来获取设备存储目录的方法为openFileOutput(String name,int mode)和openFileInput(String name),然而这两种方法的返回值是用来处理字节的文件流,分别为FileOutputStream和FileInputStream。FileReaderFileWriter为处理字符的文件流;

   2.常用的存储方式是关于字节的处理;


二:sd卡中文件的读取:

       原理和方式与设备内存文件的读取基本一样,只不过先要判断sd卡的状态,具体步骤与代码如下:

public void write(String content){                               //传入String
                   if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){             //判断sd卡状态
			File file=Environment.getExternalStorageDirectory();                        //得到sd卡根目录
			File date=new File(file,"date");                                            //创建文件
			try {
				BufferedWriter writer =new BufferedWriter(new FileWriter(date));     //为字符流添加缓存
				writer.write(content);                                               //写入数据
				writer.flush();
				writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public String read(){
	    String str="";
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			try {
				File file=Environment.getExternalStorageDirectory();
				File date=new File(file,"date");
				BufferedReader reader=new BufferedReader(new FileReader(date));           //作用同上
				String string=null;
				
				while((string=reader.readLine())!=null){                                 //判断数据是否为空,如果不加判断,程序会报错闪退
				        str=new String(reader.readLine());                               //读取每行数据,它的返回值为string类型
					reader.close();	
				}
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return str;                                                //该返回的str即转型后的by
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值