Android开发笔记之Android中数据的存储方式(一)
对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用。
总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络。其中文件和数据库可能用的稍多一些,文件用起来较为方便,程序可以自己定义格式;数据库用起稍烦锁一些,但它有它的优点,比如在海量数据时性能优越,有查询功能,可以加密,可以加锁,可以跨应用,跨平台等等;网络,则用于比较重要的事情,比如科研,勘探,航空等实时采集到的数据需要马上通过网络传输到数据处理中心进行存储并进行处理,有实时性的需求等。
对于Android平台来讲,它的存储方式也不外乎这几种,按方式总体来分,也是文件,数据库和网络。但我认为从储存标的来讲它可以细分为以下五种方式:
1.1方式
1.SharedPreferences:主要用于保存程序的系统配置信息。用来存储“key-valuespaires”。一般用于保存程序启动时设定的信息,以便在程序下一次启动时继续保留前一次设定的信息。
2.xml:保存复杂数据,比如短信备份。
3.Files:用文件的形式保存信息。可以通过对文件的读写来获取或保存相关信息。
4.SQLite:用数据库的形式保存信息。SQLite是一个开源的数据库系统。
5.NetWork:将数据保存于网络。
1.2区别
1.SharedPreferences:
Android提供用来存储一些简单的配置信息的一种机制,例如,一些默认欢迎语、登录的用户名和密码等。其以键值对的方式存储。
SharedPreferences是以XML的格式以文件的方式自动保存的,在DDMS中的FileExplorer中展开到/data/data/<packagename>/shared_prefs下,以自己的项目为例,可以看到一个叫做SETTING_Infos.xml的文件
2.Files
在Android中,其提供了openFileInput和openFileOuput方法读取设备上的文件,下面看个例子代码,具体如下所示:
StringFILE_NAME="tempfile.tmp";//确定要操作文件的文件名 FileOutputStreamfos=openFileOutput(FILE_NAME,Context.MODE_PRIVATE);//初始化 FileInputStreamfis=openFileInput(FILE_NAME);//创建写入流
上述代码中两个方法只支持读取该应用目录下的文件,读取非其自身目录下的文件将会抛出异常。需要提醒的是,如果调用FileOutputStream时指定的文件不存在,Android会自动创建它,所以不需要判断文件是否存在。另外,在默认情况下,写入的时候会覆盖原文件内容,如果想把新写入的内容附加到原文件内容后,则可以指定其模式为Context.MODE_APPEND,这里涉及到openFileOutput()的四种模式,下文我会详细解释和案例。
3.SQLite
SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库
4.NetWork:
将数据上传到网络
补充:
1.SharedPreferences底层使用xml,xml也可以保存数据,但是SharedPreferences只能保存键值对方式,xml能保存复杂数据
2.Contentprovider底部还是使用了Sqlite数据库,也是算一种方式。
1.3例子
1.SharedPreferences:
小案例:用户输入账号密码,点击登录按钮,登录的同时持久化保存账号和密码
用SharedPreference存储账号密码
•往SharedPreference里写数据
//拿到一个SharedPreference对象 SharedPreferencessp=getSharedPreferences("config",MODE_PRIVATE); //拿到编辑器 Editored=sp.edit(); //写数据 ed.putString("name",name); ed.commit();
注:这里记住put完后,必须commit一下。
•从SharedPreference里取数据
SharedPreferencessp=getSharedPreferences("config",MODE_PRIVATE); //从SharedPreference里取数据 Stringname=sp.getBoolean("name","");
•代码:
•布局文件
<LinearLayoutxmlns: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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" android:orientation="vertical" > <EditText android:id="@+id/et_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名" /> <EditText android:id="@+id/et_pass" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入密码" android:inputType="textPassword" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <CheckBox android:id="@+id/cb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="记住用户名和密码" android:layout_centerVertical="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录" android:layout_alignParentRight="true" android:onClick="login" /> </RelativeLayout> </LinearLayout>
•java代码
packagecom.bokeyuan.sharedpreference; importandroid.os.Bundle; importandroid.app.Activity; importandroid.content.SharedPreferences; importandroid.content.SharedPreferences.Editor; importandroid.view.Menu; importandroid.view.View; importandroid.widget.EditText; publicclassMainActivityextendsActivity{ privateEditTextet_name; privateEditTextet_pass; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_name=(EditText)findViewById(R.id.et_name); et_pass=(EditText)findViewById(R.id.et_pass); //拿到SharedPreferences对象 SharedPreferencessp=getSharedPreferences("info",MODE_PRIVATE); //从SharedPreferences中取出数据 Stringname=sp.getString("name",""); Stringpass=sp.getString("pass",""); et_name.setText(name); et_pass.setText(pass); } publicvoidlogin(Viewv){ Stringname=et_name.getText().toString(); Stringpass=et_pass.getText().toString(); //拿到SharedPreferences对象 SharedPreferencessp=getSharedPreferences("info",MODE_PRIVATE); //把数据存入SharedPreferences Editored=sp.edit(); ed.putString("name",name); ed.putString("pass",pass); //提交 ed.commit(); } }
2.Files
小案例:用户输入账号密码,勾选“记住账号密码”,点击登录按钮,登录的同时持久化保存账号和密码
•在内部存储空间中读写文件(RAM)
•布局文件:同上面的布局
•java代码:
packagecom.bokeyuan.rwinrom; importjava.io.BufferedReader; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importjava.io.InputStreamReader; importandroid.os.Bundle; importandroid.annotation.SuppressLint; importandroid.app.Activity; importandroid.content.Context; importandroid.view.Menu; importandroid.view.View; importandroid.widget.CheckBox; importandroid.widget.EditText; importandroid.widget.Toast; publicclassMainActivityextendsActivity{ privateEditTextet_name; privateEditTextet_pass; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_name=(EditText)findViewById(R.id.et_name); et_pass=(EditText)findViewById(R.id.et_pass); readAccount(); } @SuppressLint("ShowToast")publicvoidlogin(Viewv){ Stringname=et_name.getText().toString(); Stringpass=et_pass.getText().toString(); CheckBoxcb=(CheckBox)findViewById(R.id.cb); if(cb.isChecked()){ //指定Android的内部存储空间的路径 //Filefile=newFile("data/data/com.bokeyuan.rwinrom/info.txt"); //返回一个File对象,它的路径是:data/data/com.bokeyuan.rwinrom/files/ //Filefile=newFile(getFilesDir(),"info.txt"); //返回一个File对象,它的路径是:data/data/com.bokeyuan.rwinrom/cache/ Filefile=newFile(getCacheDir(),"info.txt"); try{ FileOutputStreamfos=newFileOutputStream(file); fos.write((name+"##"+pass).getBytes()); fos.close(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } //弹出提示框,提示用户登录成功 Toast.makeText(this,"登陆成功",0).show(); } publicvoidreadAccount(){ //指定Android的内部存储空间的路径 //Filefile=newFile("data/data/com.bokeyuan.rwinrom/info.txt"); //Filefile=newFile(getFilesDir(),"info.txt"); Filefile=newFile(getCacheDir(),"info.txt"); if(file.exists()){ try{ FileInputStreamfis=newFileInputStream(file); //把字节流转换成字符流 BufferedReaderbr=newBufferedReader(newInputStreamReader(fis)); Stringtext=br.readLine(); String[]s=text.split("##"); et_name.setText(s[0]); et_pass.setText(s[1]); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } } }
•在外部存储空间中读写文件(SD卡)
•布局文件:同上面的布局
•java代码:
packagecom.bokeyuan.rwinsd; importjava.io.BufferedReader; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importjava.io.InputStreamReader; importcom.bokeyuan.rwinsd.R; importandroid.os.Bundle; importandroid.os.Environment; importandroid.annotation.SuppressLint; importandroid.app.Activity; importandroid.content.Context; importandroid.view.Menu; importandroid.view.View; importandroid.widget.CheckBox; importandroid.widget.EditText; importandroid.widget.Toast; publicclassMainActivityextendsActivity{ privateEditTextet_name; privateEditTextet_pass; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_name=(EditText)findViewById(R.id.et_name); et_pass=(EditText)findViewById(R.id.et_pass); readAccount(); } publicvoidlogin(Viewv){ Stringname=et_name.getText().toString(); Stringpass=et_pass.getText().toString(); CheckBoxcb=(CheckBox)findViewById(R.id.cb); if(cb.isChecked()){ //检测sd卡当前是否可用 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //Filefile=newFile("sdcard/info.txt"); //返回一个file对象,包含的路径就是sd卡的真实路径 Filefile=newFile(Environment.getExternalStorageDirectory(),"info.txt"); try{ FileOutputStreamfos=newFileOutputStream(file); fos.write((name+"##"+pass).getBytes()); fos.close(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } else{ Toast.makeText(this,"sd卡不可用哟亲",0).show(); } } //弹出提示框,提示用户登录成功 Toast.makeText(this,"登陆成功",0).show(); } publicvoidreadAccount(){ //Filefile=newFile("sdcard/info.txt"); Filefile=newFile(Environment.getExternalStorageDirectory(),"info.txt"); if(file.exists()){ try{ FileInputStreamfis=newFileInputStream(file); //把字节流转换成字符流 BufferedReaderbr=newBufferedReader(newInputStreamReader(fis)); Stringtext=br.readLine(); String[]s=text.split("##"); et_name.setText(s[0]); et_pass.setText(s[1]); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } } }
注:
•//此api会把文件写到data/data/com.itheima.permission/files/文件夹下
•FileOutputStreamfos=openFileOutput("info1.txt",MODE_PRIVATE);
•//此api会把文件读到data/data/com.itheima.permission/files/文件夹下
•FileOutputStreamfos=openFileOutput("info1.txt",MODE_PRIVATE);
•所以,以后用Android自带的API。可以看下面openFileOutput四种模式的小例子:
•openFileOutput的四种模式
•MODE_PRIVATE=0:-rw-rw---- •MODE_APPEND=32768:-rw-rw---- •MODEWORLDREADABLE=1:-rw-rw-r-- •MODEWORLDWRITEABLE=2:-rw-rw--w-
Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中,可以使用Context.MODE_APPEND。
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
•注:
•在Android中,每一个应用是一个独立的用户
•drwxrwxrwx
•第1位:d表示文件夹,-表示文件
•第2-4位:rwx,表示这个文件的拥有者用户(owner)对该文件的权限•r:读
•w:写
•x:执行
•第5-7位:rwx,表示跟文件拥有者用户同组的用户(grouper)对该文件的权限
•第8-10位:rwx,表示其他用户组的用户(other)对该文件的权限
•布局文件:
<LinearLayoutxmlns: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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" android:orientation="vertical" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="创建文件1" android:onClick="click1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="创建文件2" android:onClick="click2" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="创建文件3" android:onClick="click3" /> </LinearLayout>
•代码:
packagecom.bokeyuan.permission; importjava.io.File; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importandroid.os.Bundle; importandroid.annotation.SuppressLint; importandroid.app.Activity; importandroid.view.Menu; importandroid.view.View; @SuppressLint("WorldReadableFiles") publicclassMainActivityextendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } publicvoidclick1(Viewv){ //此api会把文件写到data/data/com.bokeyuan.permission/files/文件夹下 try{ FileOutputStreamfos=openFileOutput("info1.txt",MODE_PRIVATE); fos.write("该文件是私有数据,只能被应用本身访问".getBytes()); fos.close(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } publicvoidclick2(Viewv){ //此api会把文件写到data/data/com.bokeyuan.permission/files/文件夹下 try{ @SuppressWarnings("deprecation") FileOutputStreamfos=openFileOutput("info2.txt",MODE_WORLD_READABLE|MODE_WORLD_WRITEABLE); fos.write("当前文件可以被其他应用读取或写入".getBytes()); fos.close(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } publicvoidclick3(Viewv){ //此api会把文件写到data/data/com.bokeyuan.permission/files/文件夹下 try{ @SuppressWarnings("deprecation") FileOutputStreamfos=openFileOutput("info3.txt",MODE_WORLD_WRITEABLE); fos.write("当前文件可以被其他应用写入".getBytes()); fos.close(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } }
•获取SD卡剩余容量:
•有时候读写文件的时候,需要判断SD卡的剩余容量,再进行写入操作。下面小例子,引用Android系统底层的API,获取SD卡的剩余容量。
•布局文件:
<RelativeLayoutxmlns: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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world"/> </RelativeLayout>
•Java代码:
packagecom.bokeyuan.getsdavail; importjava.io.File; importandroid.os.Build; importandroid.os.Bundle; importandroid.os.Environment; importandroid.os.StatFs; importandroid.app.Activity; importandroid.text.format.Formatter; importandroid.view.Menu; importandroid.widget.TextView; publicclassMainActivityextendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Filepath=Environment.getExternalStorageDirectory(); StatFsstat=newStatFs(path.getPath()); longblockSize; longtotalBlocks; longavailableBlocks; //检测系统当前版本号 if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN_MR2){ blockSize=stat.getBlockSizeLong(); totalBlocks=stat.getBlockCountLong(); availableBlocks=stat.getAvailableBlocksLong(); } else{ blockSize=stat.getBlockSize(); totalBlocks=stat.getBlockCount(); availableBlocks=stat.getAvailableBlocks(); } TextViewtv=(TextView)findViewById(R.id.tv); tv.setText(formatSize(availableBlocks*blockSize)); } privateStringformatSize(longsize){ returnFormatter.formatFileSize(this,size); } }
以上所述给大家介绍了Android开发笔记之Android中数据的存储方式(一)的相关知识,希望本文分享能够帮助到大家。下篇给android开发笔记之android中数据的存储方式(二),感兴趣的朋友点击了解详情。