使用内部存储器
你可以直接保存文件在设备的内部存储。默认情况下,文件保存在你的应用程序的内部存储,其他应用程序或用户不能访问。当用户卸载你的应用程序中,这些文件被删除。
(一)在内部存储创建并写入读取私有文件
- 调用openFileOutput(name,mode())方法,返回一个FileOutputStream,name参数用于指定文件名称,不能包含路径分隔符“/”,如果文件不存在,会自动创建它,创建的文件保存在/data/data/< package name>/files/目录中,model参数指定是使用方式,分别有:
MODE_PRIVATE:私有(创建此文件的应用能够使用,其他应用不能访问),写入会覆盖原来的内容。
MODE_APPEND:私有,在原有内容上增加数据
MODE_WORLD_READABLE,MODE_WORLD_WRITEABLE:可以被其他应用读取或写入(API17版本中已废弃)不建议使用
- 调用write方法吧数据写入文件
- 调用close方法关闭流
写入私有文件
/**
* 写入私有文件
* @param v
*/
public void writePrivateFileClick(View v){
try {
OutputStream out = openFileOutput("ttt.txt", Context.MODE_PRIVATE);
String info = "劝君更尽一杯酒";
byte[] bytes = info.getBytes();
out.write(bytes,0,bytes.length);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
读取私有文件
public void readPrivateFileClick(View v){
try {
InputStream in = openFileInput("ttt.txt");
byte[] bytes = new byte[1024];
StringBuffer sb = new StringBuffer();
int len = -1;
while ((len=in.read(bytes))!=-1){
sb.append(new String(bytes,0,len));
}
in.close();
Toast.makeText(this,sb,Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
(二)保存内部缓存文件
如果你想缓存一些数据,而不是永久保存,可以使用getCacheDir()打开文件所在的目录,代表内部应用程序应保存临时缓存文件。
当设备的内部存储空间低,Android可以删除这些缓存文件以回收空间。然而,你不应该以来系统来为你清除这些文件。你应该自己维护缓存文件,并保持在一个合理的消耗空间的限制,如1MB。当用户卸载你的应用程序,这些文件被删除。
通过getCacheDir()获取的目录为:/data/data/< package name>/cache
方法 | 作用 | 作用的目录 |
---|---|---|
getFileDir(): | 获取私有文件目录 | /data/data/< package name>/files |
getDir(name,model): | 创建(或打开已存在的)目录 | /data/data/< package name>/app_< 文件名> |
deleteFile(name): | 删除私有目录的文件 | /data/data/< package name>/files |
fileList(): | 获取/data/data/< package name>/files目录的文件名数组 |
public void writePrivateCacheDataClick(View v){
// String temp = getCacheDir() + "/temp.tmp";
try {
//创建一个缓存的文件
File temp = File.createTempFile("temp",null,getCacheDir());
FileOutputStream out = new FileOutputStream(temp);
PrintStream ps = new PrintStream(out);
ps.print("朝辞白帝彩云间");
ps.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
使用外部存储器
所有兼容Android的设备都支持一个可共享的“外部存储”,可用来保存文件。这可以使一个可以的的存储设备(比如SD卡)或者一个内部的(不可以的的)存储。保存在外部存储的文件是可读的。并且当用于传输数据的USB大容量存储选项启用时,用户能够在计算机上修改它们。
(一)获取外部存储权限
为了在外部存储读写文件,必须获得
< uses-permission android:name=“android.permission.READ_EXTERNAL_STORAGE”/>
< uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE”/>
的系统权限。
要读也要写权限,可添加
< uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE”/>
(二)检查媒体的可用性
在使用外部存储来保存数据时,我们应该使用getExtetrnalStorageState()来检查当前设备是否存在外部存储设备(SDCard),否则将会发生意外
public void isSDCardClick(View v){
//判断是否有SDCard
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
Toast.makeText(this,"有SDCard",Toast.LENGTH_SHORT).show();
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY)){
Toast.makeText(this,"SDCard只读",Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(this,"没有SDCard",Toast.LENGTH_SHORT).show();
}
}
(三)访问SDCard路径
以前的Android(4.1以前的版本)中,SDcard路径通过“/sdcard”或者“/mnt/sdcard”来表示,
而在Jelly Bean系统中修改为了“/storage/sdcard0”,以后肯还会有多个SDCard的情况。
目前为了保持和之前代码的兼容,sdcard路径做了link映射。
为了使代码更加见状并能兼容以后的Android版本和新设备,请通过Environment.getExternalStorageDirectory().getPath()来获取sdcard路径
可以使用Environment.getExternalStoragePublicDirectory(String type)函数,返回特定类型的目录:
类型 | |
---|---|
DIRECTORY_ALARMS | 警报的临时 |
DIRECTORY_DCIM | 相机拍摄的图片和视频位置 |
DIRECTORY_DOWNLOADS | 下载文件保存的位置 |
DIRECTORY_MOVIES | 电影保存的位置 |
DIRECTORY_MUSIC | 音乐保存的位置 |
DIRECTORY_NOTIFICATIONS | 通知音保存的位置 |
DIRECTORY_PICTURES | 下载的图片保存的位置 |
DIRECTORY_PODCASTS | 永远忽保存podcast(博客)的音频文件 |
DIRECTORY_RINGTONES | 保存铃声的位置 |
(四)Saving files that are app-private(保存文件私有化)4.4版本后可用
为了文件的保密性,你必须保证自己的文件不让其他app读取,你可以使用getExternalFilesDir(type),type为null为默认。
再次注意,getExternalFilesDir()这个方法,不一定总能访问sd卡中的信息。
如果设备资深已经有了一部分内部存储当做外部存储,那这个方法就不能访问到sd。
当用户卸载应用程序时,Android系统删除以下:
(1)你保存在内部存储的所有文件
(2)所有使用本应用外部存储的私有文件
public void writeSDcardPrivateFileClick(View v){
File file = getExternalFilesDir(null);
if(file!=null){
FileOutputStream out = null;
try {
out = new FileOutputStream(file+"/yyy.txt");
PrintStream ps = new PrintStream(out);
ps.print("渭城朝雨浥轻尘");
ps.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(五)外部存储保存私有缓存文件
通过Context.getExternalFilesDir()可以获取到 SDCard/Android/data/你的应用的包名/files/目录 ,一般存放长时间保存的数据,
通过Context.getExternalCacheDir()可以获取到 SDCard/Android/data/你的应用的包名/cache/ 目录,一般存放临时缓存数据
如果使用上面的方法,在应用被用户卸载后, SDCard/Android/data/你的应用的包名/ 这个目录下单所有文件都会被删除,不会留下垃圾文件,而且上面二个目录分别对应 设置->应用->应用详情里面的“清除数据”与“清除缓存”选项
//写入SDCARD 私有缓存文件
public void writeSDcardPrivateCacheFileClick(View v){
try {
File temp = File.createTempFile("xxx",null,getExternalCacheDir());
if(temp!=null){
FileOutputStream out = new FileOutputStream(temp);
PrintStream ps = new PrintStream(out);
ps.print("渭城朝雨浥轻尘");
ps.close();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
XML解析
(一)XML解析的两种机制
xml是一种常用的存储数据方式,在Android平台中内部很多地方使用了xml存储,比如轻量级的SharedPreference类的存储就是使用了xml文件。
xml解析主要有三张方式,SAX(Simple API for XML),DOM(Document Object Model)和Android附带的PULL解析器解析XML文件。
常规PC开发我们使用DOM,淡一些性能敏感的数据库或手机上还是采用SAX方式,SAX读取是单向的,优点是不占内存空间,解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便,而DOM方式会把整个XML文件加载到内存中去,优点是可以任意读取节点,但缺点是会消耗内存,而PULL常常用在移动设备对于节点处理比较好,类似SAX方式,同样很节省内存。
(二)PULL解析
Pull解析器的运行方式与SAX相似。它提供了类似的事件,如开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.next()方法可以获取下一个Text类型元素的值。
<!--创建xml文件-->
<codingke>
<person personid="1">
<name>ttt</name>
<age>18</age>
<sex>男</sex>
<tel>138456784569</tel>
</person>
<person personid="2">
<name>yyy</name>
<age>15</age>
<sex>女</sex>
<tel>13632145875</tel>
</person>
</codingke>
<!--同时要创建一个Person类-->
public void pullParserClick(View v){
ArrayList<Person> list = parser();
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
private ArrayList<Person> parser(){
ArrayList<Person> list = new ArrayList<>();
Person p = null;
//创建PULL解析器
XmlPullParser pull = Xml.newPullParser();
// StringReader sr = new StringReader(xml);
InputStream in = getResources().openRawResource(R.raw.person);
try {
//设置要解析的文件流
pull.setInput(in,"UTF-8");
//获取当前事件类型
int eventType = pull.getEventType();
while (eventType!=XmlPullParser.END_DOCUMENT){
switch (eventType){
case XmlPullParser.START_TAG:
String tag = pull.getName();
if("person".equals(tag)){
p = new Person();
p.personid = Integer.parseInt(pull.getAttributeValue(null,"personid"));
}else if ("name".equals(tag)){
p.name = pull.nextText();
}else if ("age".equals(tag)){
p.age = Integer.parseInt(pull.nextText());
}else if ("sex".equals(tag)){
p.sex = pull.nextText();
}else if("tel".equals(tag)){
p.tel = pull.nextText();
}
break;
case XmlPullParser.END_TAG:
if ("person".equals(pull.getName())){
list.add(p);
}
break;
}
//获取下一个时间类型
eventType = pull.next();
}
} catch (XmlPullParserException | IOException e) {
e.printStackTrace();
}
return list;
}
JSON解析
(一)什么是JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。
JSON数据格式的特点
JSON建构于两种结构:
1、“名称/值”对的集合:{“firstName”:“Li”,“lastName”:“Si”}
2、值的有序列表(数组):{“user”:[
{“firstName”:“Li”,“lastName”:“Si”,“email”:“123456@qq.com”},
{“firstName”:“Zhang”,“lastName”:“San”,“email”:“789456@qq.com”}]}
(二)使用JsonReader解析JSON数据
JSONReader是Android.util包下一个用于解析JSON的工具类
JsonReader reader = new JsonReader(new StringReader(jsonData))
public void jsonReaderClick(View v){
ArrayList<Worker> list = jsonReader();
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
private ArrayList<Worker> jsonReader(){
// String json = "{\"user\":[{\"firstName\":\"Li\",\"lastName\":\"Si\",\"email\":\"123456@qq.com\"}," +
// "{\"firstName\":\"Zhang\",\"lastName\":\"San\",\"email\":\"789456@qq.com\"}]}";
ArrayList<Worker> list = new ArrayList<>();
Reader r = new InputStreamReader(getResources().openRawResource(R.raw.worker));
JsonReader jr = new JsonReader(r);
try {
jr.beginObject();
if(jr.hasNext()){
if ("user".equals(jr.nextName())){
jr.beginArray();//开始解析数组
while (jr.hasNext()){
Worker w = new Worker();
jr.beginObject();//开始解析对象
while (jr.hasNext()){
String name = jr.nextName();
if("firstName".equals(name)){
w.firstName = jr.nextString();
}else if ("lastName".equals(name)){
w.lastName = jr.nextString();
}else if("email".equals(name)){
w.email = jr.nextString();
}
}
jr.endObject();//结束对象的解析
list.add(w);
}
jr.endArray();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
json数据:
{"user":
[{"firstName":"Li","lastName":"Si","email":"123456@qq.com"},
{"firstName":"Zhang","lastName":"San","email":"789456@qq.com"}]
}
(三)生成一组JSON数据
public void createJSONClick(View v){
ArrayList<Worker> list = new ArrayList<>();
Worker w1 = new Worker();
w1.firstName = "Wang";
w1.lastName = "Wu";
w1.email = "456123@qq.com";
Worker w2 = new Worker();
w2.firstName = "Zhao";
w2.lastName = "Liu";
w2.email = "741852@qq.com";
list.add(w1);
list.add(w2);
JSONObject json = new JSONObject();
JSONArray array = new JSONArray();
try {
for (int i=0;i<list.size();i++){
Worker w = list.get(i);
JSONObject obj = new JSONObject();
obj.put("firstName",w.firstName);
obj.put("lastName",w.lastName);
obj.put("email",w.email);
array.put(obj);
}
json.put("worker",array);
} catch (JSONException e) {
e.printStackTrace();
}
//测试
System.out.println(json.toString());
}
(四)GSON的使用
//使用GSON解析JSON
public void gsonParseJsonClick(View v){
Gson gson = new Gson();
Reader r = new InputStreamReader(getResources().openRawResource(R.raw.worker));
Type type = new TypeToken<ArrayList<Worker>>(){}.getType();
ArrayList<Worker> list = gson.fromJson(r,type);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
// class MyTypeToken extends TypeToken<ArrayList<Worker>>{}
//GSON生成JSON
public void gsonToJsonClick(View v){
ArrayList<Worker> list = new ArrayList<>();
Worker w1 = new Worker();
w1.firstName = "Wang";
w1.lastName = "Wu";
w1.email = "456123@qq.com";
Worker w2 = new Worker();
w2.firstName = "Zhao";
w2.lastName = "Liu";
w2.email = "741852@qq.com";
list.add(w1);
list.add(w2);
Gson gson = new Gson();
Type type = new TypeToken<ArrayList<Worker>>(){}.getType();
String json = gson.toJson(list,type);
System.out.println(json);
}
json数据:
[{"firstName":"Li","lastName":"Si","email":"123456@qq.com"},
{"firstName":"Zhang","lastName":"San","email":"789456@qq.com"}]
(五)JSON vs XML
1、JSON和XML的数据可读性基本相同
2、JSON和XML同样拥有丰富的解析手段
3、JSON相对于XML来讲,数据的体积小
4、JSON与JavaScript的交互更加方便
5、JSON对数据的描述性比XML差
6、JSON的速度要远远快于XML