android的数据储存(1)(SharedPreference、File)
一、有些时候程序有少量的数据需要存储时,而且格式简单,是普通的字符串,标量等,对于这种数据android提供了SharedPreference进行保存。
二、SharedPreference保存的数据是简单的key--value对,SharedPreference接口主要负责,读取应用程序的SharedPreference数据,而SharedPreference是没有写的能力,只有读的能力。
由于SharedPreference是接口,是无法直接创建实例,只有通过Context提供的getSharedPreferences(String name,int mode)
name:为数据保存的文件名
mode:可以有三个,但是其中有两个是不安全的,android已经不再推荐了。所以mode用:MODE_PRIVATE
1、boolean contains(String key):判断SharedPreference是否包含特定的key
2、abstract Map<String,?> getAll():获取SharedPreference中的全部key--value对3、
3、boolean getXxx(String key, xx defValue):获取SharedPreference指定的key--value,如果存在value则返回,如果不存在就返回defValue默认值。其中xx可以是boolean,flaot,int,long,String等。
三、要实现数据的写入,要使用Editor对象,此对象是通过SharedPreference调用edit()方法得到、Editor对象提供如下的方法对数据的写入。
1、SharedPreference.Editor clear():清空SharedPreference里面的所有数据
2、SharedPreference.Editor putXxx(String key,xxx value):向SharedPreference里面存入指定key对的数据,xxx可以是boolean,flaot,int,long,String等。
3、SharedPreference.Editor remove(String key):删除SharedPreference里面指定的key对数据项
4、boolean commit():当Editor编辑完成后,调用该方法提交修改
实例:对SharedPreference数据进行操作
1、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="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/write" android:text="write"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/read" android:text="read"/> </LinearLayout>
2、activity
public class SharedPreferencesActivity extends AppCompatActivity { SharedPreferences sharedPreferences; SharedPreferences.Editor editor; static int count; public void onCreate(Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.sharedpreferences_activity); sharedPreferences=getSharedPreferences("crazyit",MODE_PRIVATE); //sharedPreferences为接口,无法直接创建,调用context中的方法,实例化sharedPreferences,进行对数据的读 editor=sharedPreferences.edit(); //调用方法获得Editor对象,对数据进行写 Button write=findViewById(R.id.write); Button read=findViewById(R.id.read); count=sharedPreferences.getInt("count",0); write.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"+"hh:mm:ss"); editor.putString("time",sdf.format(new Date())); //写入日期 editor.putInt("random",(int)(Math.random()*100)); //写入一个整数 editor.putInt("count",++count); //写入count editor.commit(); //提交修改 } }); read.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //进行读 String time=sharedPreferences.getString("time",null); int random=sharedPreferences.getInt("random",0); int count1=sharedPreferences.getInt("count",0); Toast.makeText(SharedPreferencesActivity.this,time+" "+random+" "+count1,Toast.LENGTH_SHORT).show(); } }); } }
四、File存储
一、Context提供了如下的两种方式打开程序数据文件的io流
1、FileInputStream openFileInput(String name):打开应用程序数据文件下的name文件对应输入流,对于读数据
2、FileOutputStream openFileOutput(String name,int mode):打开应用程序的数据文件下name文件对应的输入流,对应写数据,
其中mode对应三个模式,但是其中两个已经不推荐使用,所以mode:MODE_PRIVATE
二、Context还提供了如下的几种方式访问应用程序的数据文件
1、getDir(String name,int mdoe):在应用程序的数据文件夹下获取或创建name对应的子目录
2、File getFilesDir():获取应用程序的数据文件的绝对路径
3、String[] fileList():返回应用程序文件夹下的全部文件
4、deleteFile(String):删除应用程序的数据文件指定的文件
向程序数据文件夹内输入数据:
//以追加的方式打开文件夹的输入流 FileOutputStream fos=openFileOutput(FILE_NAME,MODE_PRIVATE); //将FileOutputStream封装成printStream PrintStream ps=new PrintStream(fos); //输出内容到文件 ps.print(content); ps.close();
向应用程序数据文件读数据
//打开name程序数据文件流输入流 FileInputStream fil=openFileInput(FILE_NAME); //用于接收每次读出的数据 byte[] buff=new byte[1024]; int hasRead=0; //读取出来的全部数据 StringBuilder builder=new StringBuilder(); while((hasRead=fil.read(buff))>0){ //判断数据是否读完 builder.append(new String(buff,0,hasRead)); } //关闭文件流 fil.close();
实例:程序写如数据到程序文件夹内,在读取文件夹里面的内容
public class FileActivity extends AppCompatActivity{ private String FILE_NAME="/crazyit.bin"; EditText editText1; EditText editText2; protected void onCreate(Bundle saveInstanceSate) { super.onCreate(saveInstanceSate); LinearLayout linearLayout=new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); Button read=new Button(this); Button write=new Button(this); read.setText("read"); write.setText("write"); editText1=new EditText(this); editText2=new EditText(this); linearLayout.addView(write); linearLayout.addView(editText1); linearLayout.addView(read); linearLayout.addView(editText2); setContentView(linearLayout); read.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { editText2.setText(read()); } }); write.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { write(editText1.getText().toString()); editText1.setText(""); } }); } private String read(){ //向应用程序的数据文件夹read try{ FileInputStream fil=openFileInput(FILE_NAME); byte[] buff=new byte[1024]; int hasRead=0; StringBuilder builder=new StringBuilder(); while((hasRead=fil.read(buff))>0){ builder.append(new String(buff,0,hasRead)); } //关闭文件流 fil.close(); return builder.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private void write(String content) { //向应用程序的数据文件夹write try{ FileOutputStream fos=openFileOutput(FILE_NAME,MODE_PRIVATE); //将FileOutputStream封装成printStream PrintStream ps=new PrintStream(fos); ps.print(content); ps.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
五、读取SD卡上的文件
一、为了更好地存取应用程序地大文件,应用程序需要读写SD卡上的文件,SD卡大大地扩充了手机地存储功能。分为几个步骤。
1、调用Environment的getExteranlStorageState():方法判断手机是否插入SD卡,并且应用程序具有读写的SD卡的权限。
//如果手机已插入sd卡,且应用程序具有对鞋SD卡的能力,下面返回false
Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)
2、调用Environment的getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录
3、使用FileInputStream,FileOutputStream ,FileRead或者FileWrite(),方法来读写SD卡
4、读写SD卡是一个危险权限,需要在androidManifest.xml文件中声明权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> //sd卡中删除文件权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> //sd卡中读写文件权限
SD卡读:
//如果手机插入SD卡,而且应用程序具有访问sd卡的权限 if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //获取sd卡对应的存储目录 File sdCardDir=Environment.getExternalStorageDirectory(); //获取指定文件的输入流 FileInputStream fis=new FileInputStream(sdCardDir.getCanonicalPath()+FILE_NAME); //将指定的输入流包装成BBufferedReader BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(fis)); StringBuilder builder=new StringBuilder(""); String line=null; while ((line=bufferedReader.readLine())!=null){ builder.append(line); } bufferedReader.close(); return builder.toString(); }
SD卡写:
if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //获取sd卡对应的存储目录 Toast.makeText(FileActivity.this,"有权限",Toast.LENGTH_SHORT).show(); File sdCardDir=Environment.getExternalStorageDirectory(); File targetFile=new File(sdCardDir.getCanonicalPath()+FILE_NAME); Toast.makeText(FileActivity.this,sdCardDir.getCanonicalPath()+FILE_NAME,Toast.LENGTH_SHORT).show(); //将指定文件创建RandomAccessFile对象 //这里使用RandomAccessFile向SD卡中指定追加内容,如果使用FileOutputStream向指定文件写数据会将原有的文件内容清空,而不是追加的方式 RandomAccessFile raf=new RandomAccessFile(targetFile,"rw"); //将文件的指针移动到最后面 raf.seek(targetFile.length()); //输出文件内容 raf.write(content.getBytes()); Toast.makeText(FileActivity.this,"完成",Toast.LENGTH_SHORT).show(); raf.close(); }
实例:读写sd卡中的数据
public class FileActivity extends AppCompatActivity{ private String FILE_NAME="/crazyit.bin"; EditText editText1; EditText editText2; protected void onCreate(Bundle saveInstanceSate) { super.onCreate(saveInstanceSate); LinearLayout linearLayout=new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); Button read=new Button(this); Button write=new Button(this); read.setText("read"); write.setText("write"); editText1=new EditText(this); editText2=new EditText(this); linearLayout.addView(write); linearLayout.addView(editText1); linearLayout.addView(read); linearLayout.addView(editText2); setContentView(linearLayout); read.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { editText2.setText(read()); } }); write.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { write(editText1.getText().toString()); editText1.setText(""); } }); } private String read(){ //SD卡读 try{ //如果手机插入SD卡,而且应用程序具有访问sd卡的权限 if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //获取sd卡对应的存储目录 File sdCardDir=Environment.getExternalStorageDirectory(); //获取指定文件的输入流 FileInputStream fis=new FileInputStream(sdCardDir.getCanonicalPath()+FILE_NAME); //将指定的输入流包装成BBufferedReader BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(fis)); StringBuilder builder=new StringBuilder(""); String line=null; while ((line=bufferedReader.readLine())!=null){ builder.append(line); } bufferedReader.close(); return builder.toString(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private void write(String content) { //SD卡写 try{ //如果手机插入SD卡,而且应用程序具有访问sd卡的权限 if(!Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)){ //获取sd卡对应的存储目录 Toast.makeText(FileActivity.this,"有权限",Toast.LENGTH_SHORT).show(); File sdCardDir=Environment.getExternalStorageDirectory(); File targetFile=new File(sdCardDir.getCanonicalPath()+FILE_NAME); Toast.makeText(FileActivity.this,sdCardDir.getCanonicalPath()+FILE_NAME,Toast.LENGTH_SHORT).show(); //将指定文件创建RandomAccessFile对象 //这里使用RandomAccessFile向SD卡中指定追加内容,如果使用FileOutputStream向指定文件写数据会将原有的文件内容清空,而不是追加的方式 RandomAccessFile raf=new RandomAccessFile(targetFile,"rw"); //将文件的指针移动到最后面 raf.seek(targetFile.length()); //输出文件内容 raf.write(content.getBytes()); Toast.makeText(FileActivity.this,"完成",Toast.LENGTH_SHORT).show(); raf.close(); } } catch (IOException e) { e.printStackTrace(); } } }
实例:sd卡文件夹浏览器
(如果开发者不想用Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED),也可以使用/mnt/sdcard/路径代表SD卡路径
1、xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/path" android:textSize="20sp" android:layout_gravity="center_horizontal" android:layout_alignParentTop="true"/> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/list" android:divider="#000" android:dividerHeight="1px" android:layout_below="@+id/path"/> <Button android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/pzb" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:id="@+id/parent"/> </RelativeLayout>
2、activity
public class FileListActivity extends AppCompatActivity { ListView listView; TextView textView; //当前父目录 File currentParent; File[] currentFiles; public void onCreate(Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.listfile_activity); listView=findViewById(R.id.list); textView=findViewById(R.id.path); //获取系统的SD卡的目录 File root=new File("/mnt/sdcard/"); //如果SD卡存在 if(root.exists()){ currentParent=root; currentFiles=root.listFiles(); //使用当前目录下面的全部文件,文件夹来填充listView inflateListView(currentFiles); } //为listview的列表的单击事件绑定监听器 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { //如果用户点击文件不是,直接返回,不做任何处理 if(currentFiles[i].isFile()) return ; //获取用户点击的文件夹下面的文件夹 File []tmp=currentFiles[i].listFiles(); if(tmp==null||tmp.length==0){ Toast.makeText(FileListActivity.this,"当前的路径不可访问,该路径下面没有文件",Toast.LENGTH_SHORT).show(); }else { //获取用户单击的列表项对应的文件夹,设当前的文件夹为父文件夹 currentParent=currentFiles[i]; //保存当前点的父文件夹的全部内容 currentFiles=tmp; //再次更新ListView inflateListView(currentFiles); } } }); //获取上一级目录按钮 Button parent=findViewById(R.id.parent); parent.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { if(!currentParent.getCanonicalPath().equals("/mnt/sdcard")){ //获取上一级目录 currentParent=currentParent.getParentFile(); //列出当前目录下面的所有文件 currentFiles=currentParent.listFiles(); //再次更新listView inflateListView(currentFiles); } } catch (IOException e) { e.printStackTrace(); } } }); } private void inflateListView(File[] files){ //创建一个list集合,list集合的元素是Map List<Map<String,Object>> list=new ArrayList<Map<String,Object>>(); for(int i=0;i<files.length;i++){ Map<String,Object> listItem=new HashMap<String,Object>(); //如果当前的file是文件,使用folder图标,否则使用file图标 if(files[i].isDirectory()){ listItem.put("icon",R.drawable.p7txxw); } else{ listItem.put("icon",R.drawable.tp); } listItem.put("fileName",files[i].getName()); //添加list项 list.add(listItem); } SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.filelist_item,new String[]{"icon","fileName"},new int[]{R.id.file_image,R.id.file_name}); listView.setAdapter(adapter); try{ textView.setText("当前目录:"+currentParent.getCanonicalPath()); } catch (IOException e) { e.printStackTrace(); } } }