下面详细解释这四大方式的特点
第一种:文件存储数据
核心原理: Context提供了两个方法来打开数据文件里的文件IO流 FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。具体有以下值可选:
MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可 以使用Context.MODE_APPEND
MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;
MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
除此之外,Context还提供了如下几个重要的方法:
getDir(String name , int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录
File getFilesDir():获取该应用程序的数据文件夹得绝对路径
String[] fileList():返回该应用数据文件夹的全部文件
实例:
核心代码:
布局:
<LinearLayout 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" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名" android:id="@+id/name"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入密码" android:id="@+id/pwd" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存" android:onClick="mybtn1"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="读取" android:onClick="mybtn2"/> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:textSize="35sp" android:id="@+id/tv"/> </LinearLayout>
activity中:
filename:
private String filename="info.txt";
保存:
public void mybtn1(View view) { // TODO Auto-generated method stub String Name=name.getText().toString(); String Pwd=pwd.getText().toString(); try { //字节文件输出流是用于将数据写入到File FileOutputStream fos=openFileOutput(filename, MODE_APPEND); PrintWriter out=new PrintWriter(fos); out.println(Name); out.println(Pwd); out.flush(); try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } out.close(); name.setText(""); pwd.setText(""); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
读取:
public void mybtn2(View view) { // TODO Auto-generated method stub try { FileInputStream fis=openFileInput(filename); //字节转换成字符流,再转换为缓冲字符流 BufferedReader br=new BufferedReader(new InputStreamReader(fis)); String line=null; StringBuilder sb=new StringBuilder(); try { while((line=br.readLine())!=null){ sb.append(line+"\n"); tv.setText(sb.toString()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
效果图:
第二种:SD卡存储数据
其中读写步骤按如下进行:
1、调用Environment的getExternalStorageState()方法判断手机上是否插了sd卡,且应用程序具有读写SD卡的权限,如下代码将返回true
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
2、调用Environment.getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录,或者使用"/mnt/sdcard/"目录
3、使用IO流操作SD卡上的文件
注意点:手机应该已插入SD卡,对于模拟器而言,可通过mksdcard命令来创建虚拟存储卡
必须在AndroidManifest.xml上配置读写SD卡的权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
实例:
核心代码:
布局:用上面的布局
activity:
filename:
private String filename="my.txt";
保存:
public void mybtn1(View view) { // TODO Auto-generated method stub String Name=name.getText().toString(); String Pwd=pwd.getText().toString(); //1.判断SD可用否 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //2.获取路径 String path=Environment.getExternalStorageDirectory().getAbsolutePath(); //3.获取流对象进行读写操作 try { PrintWriter out=new PrintWriter(new FileOutputStream(path+"/"+filename)); out.println(Name); out.println(Pwd); out.flush(); name.setText(""); pwd.setText(""); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ Toast.makeText(this, "SD卡不可用", 0).show(); } }
读取:
public void mybtn2(View view) { // TODO Auto-generated method stub if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //2. String path=Environment.getExternalStorageDirectory().getAbsolutePath(); //3. try { BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(path+"/"+filename))); String line=null; StringBuilder sb=new StringBuilder(); try { while((line=br.readLine())!=null){ sb.append(line+"\n"); tv.setText(sb.toString()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } name.setText(""); pwd.setText(""); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else{ Toast.makeText(this, "SD卡不可用", 0).show(); } }
效果图:
第三种:Shared Preferences存储数据
适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型、基本类型的值。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口 令密码等
核心原理:保存基于XML文件存储的key-value键值对数据,通常用来存储一些简单的配置信息。通过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据总是存储在/data/data/<package
name>/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过SharedPreferences.edit()获取的内部接口Editor对象实现。 SharedPreferences本身是一
个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例,该方法中name表示要操作的xml文件名,第二个参数具体如下:
Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写。
Context.MODE_WORLD_READABLE: 指定该SharedPreferences数据能被其他应用程序读,但不能写。
Context.MODE_WORLD_WRITEABLE: 指定该SharedPreferences数据能被其他应用程序读,写
Editor有如下主要重要方法:
SharedPreferences.Editor clear():清空SharedPreferences里所有数据
SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key对应的数据,其中xxx 可以是boolean,float,int等各种基本类型据
SharedPreferences.Editor remove(): 删除SharedPreferences中指定key对应的数据项
boolean commit(): 当Editor编辑完成后,使用该方法提交修改
实例:
布局:用上面第一种的代码
activity中:
保存:
public void mybtn1(View view){ String Name=name.getText().toString(); String Pwd=pwd.getText().toString(); editor.putString("name", Name); editor.putString("pwd", Pwd); editor.putInt("count", 100); editor.putBoolean("sound", true); //提供修改之后的数据 editor.commit(); name.setText(""); pwd.setText(""); }
读取:
public void mybtn2(View view){ String n=sp.getString("name", ""); String p=sp.getString("pwd", ""); int c=sp.getInt("count", 0); boolean b=sp.getBoolean("sound", false); tv.setText("姓名:"+n+"\n"+"密码:"+p+"\n"+"次数:"+c+"\n"+"sound:"+b+"\n"); }
效果图:
第四种:SQLite存储数据
SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。现在的主流移动设备像Android、iPhone等都使用SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上的SQLite开发技巧
SQLiteDatabase类为我们提供了很多种方法,上面的代码中基本上囊括了大部分的数据库操作,现在我写了数据库帮助类实现了数据库的创建和更新
实例:
布局:
<LinearLayout 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" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名" android:id="@+id/name"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入密码" android:id="@+id/pwd" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存" android:onClick="mybtn1"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="读取" android:onClick="mybtn2"/> </LinearLayout> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/lv"/> </LinearLayout>
activity:
package com.example.fileapp; import android.os.Bundle; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.EditText; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; public class FourActivity extends Activity { private EditText nameEt,pwdEt; private ListView lv; private MyOpenHelper helper; //代表数据库对象 private SQLiteDatabase db; public void mybtn1(View view){ String name=nameEt.getText().toString(); String pwd=pwdEt.getText().toString(); //try { insert(db,name,pwd); //} catch (Exception e) { // create(db); // insert(db,name,pwd); //} } private void create(SQLiteDatabase db) { String sql="create table s_user(_id integer primary key autoincrement,name text,pwd text)"; db.execSQL(sql); } public void insert(SQLiteDatabase db,String name,String pwd){ /*String sql="insert into s_user("+"name,pwd)values(?,?)"; db.execSQL(sql,new String[]{name,pwd});*/ //使用特定的方法:insert ContentValues values=new ContentValues(); //key是字段名,value是插入的名字 values.put("name", name); values.put("pwd", pwd); db.insert("s_user", null, values); nameEt.setText(""); pwdEt.setText(""); } public void mybtn2(View view){ /*String sql="select * from s_user"; Cursor cursor=db.rawQuery(sql, null); */ //使用特定的方法 // Cursor cursor=db.query("s_user", null,null,null,null,null,null); refresh(cursor); } private void refresh(Cursor cursor){ SimpleCursorAdapter adapter=new SimpleCursorAdapter( this, R.layout.activity_item, cursor, new String[]{"_id","name","pwd"}, new int[]{R.id.id,R.id.name,R.id.pwd}, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); lv.setAdapter(adapter); } protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_four); nameEt=(EditText)findViewById(R.id.name); pwdEt=(EditText)findViewById(R.id.pwd); lv=(ListView)findViewById(R.id.lv); lv.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub TextView tv=(TextView) view.findViewById(R.id.id); String pid=tv.getText().toString(); /*String sql= "delete from s_user where _id="+pid; db.execSQL(sql);*/ //使用特定方法 db.delete("s_user", "_id=?", new String[]{pid}); refresh(db.rawQuery("select *from s_user", null)); return true; } }); //第一种方式:获取数据库对象 //第一个参数:数据库文件的路径 //第二个参数:游标的工厂对象 //db=SQLiteDatabase.openOrCreateDatabase(getFilesDir()+"/my.db", null); //第二种方式:获取数据库对象(方式更好) helper=new MyOpenHelper(this, "user.db", null, 1); db=helper.getReadableDatabase(); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); //关闭数据库 helper.close(); } }
帮助类MyOpenHelper:
package com.example.fileapp; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; //数据库的帮助类:创建数据库表和数据库的更新 public class MyOpenHelper extends SQLiteOpenHelper{ //定义该程序中每张表的建表语句 private String sql1="create table s_user(_id integer primary key autoincrement,name,pwd)"; //第二个参数是数据库的名字,第三个是游标工厂对象,第四个是参数当前数据库使用版本号 public MyOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub } //用于创建数据库表,第一次创建数据库文件时被回调 @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL(sql1); } //用于数据库的更新,旧版本号和新版本号不一致会被回调 @Override public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { // TODO Auto-generated method stub } }
效果图: