一. 数据存储与访问
Android为数据存数提供了多种方式:
1> 文件
2> SharedPreferences
3> SQLite数据库
4> 内容提供者
5> 网络
二. 使用文件进行数据存储
Activity提供了openFileOutput()方法可以用于把数据输出到文件中(具体的实现过程和J2SE环境中保存数据在文件中是一样的)
1.openFileOutput() 方法的第一个参数用于指定文件名称,不能包含路径分隔符”/”.如果文件不存在,Android会自动创建它。创建的文件保存在/data/data/<package name>/files目录。
2.openFileOutput()方法的第二个参数用于指定操作模式,有四种操作模式,分别为:
Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
案例:
publicclass AFileActivity extends Activity {
/** Called when the activity is first created. */
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
// 输出 写
FileOutputStream fos = openFileOutput("file.txt",
Activity.MODE_PRIVATE);
String con = "文件存储的方式";
fos.write(con.getBytes("UTF-8"));
fos.close();
// 输入 读
FileInputStream fis = openFileInput("file.txt");
byte buffer[] = newbyte[1024];
int bytec = 0;
String str = "";
while ((bytec = fis.read(buffer)) != -1) {
str += new String(buffer, 0, bytec, "UTF-8");
}
TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(str);
fis.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.Activity还提供了getCacheDir()和getFilesDir()方法:
getCacheDir()方法用于获取/data/data/<package name>/cache目录
getFilesDir()方法用于获取/data/data/<package name>/files目录
三. 把文件存放到SDCard中
使用Activity的openFileOutput()方法保存文件,文件是存放在手机空间上,一般手机的存储空间不是很大,存放些小文件还行,如果要存放像视频这样的大文件,是不可行的。对于像视频这样的大文件,我们可以把它存放在SDCard。你可以把它看作是移动硬盘或U盘。
1.在程序中访问SDCard,你需要申请访问SDCard的权限。
在AndroidManifest.xml中加入访问SDCard的权限如下:
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2.把文件存放在SDCard
publicclass ASdcardActivity extends Activity {
/** Called when the activity is first created. */
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
// 判断手机是否有sdcard
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
// 获取SDCard 目录
File dirPath = Environment.getExternalStorageDirectory();
// 写入sdCard中
// String dirPath="/mnt/sdcard";
// 创建你要写入的文件
File file = new File(dirPath, "csdn.txt");
//输出 写
FileOutputStream fos = new FileOutputStream(file);
fos.write("你好".getBytes("utf-8"));
fos.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
四. 使用SAX或者DOM解析XML文件
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。下面是一些ContentHandler接口常用的方法:
startDocument()
当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument()
和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURI, String localName, String qName, Attributes atts)
当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。
endElement(String uri, String localName, String name)
这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch, int start, int length)
这个方法用来处理在XML文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
在实际开发中继承类DefaultHandler。
案例解析:
Persons.xml
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>李明</name>
<age>30</age>
</person>
<person id="20">
<name>李向梅</name>
<age>25</age>
</person>
</persons>
Person.java
publicclass Person implements Serializable{
/**
*
*/
privatestaticfinallongserialVersionUID = 1L;
private Integer id;
private String name;
private Integer age;
public Integer getId() {
returnid;
}
publicvoid setId(Integer id) {
this.id = id;
}
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
public Integer getAge() {
returnage;
}
publicvoid setAge(Integer age) {
this.age = age;
}
public Person(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return"Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
Saxxml.java
publicclass Saxxml extends DefaultHandler {
//对象要在startElement方法中实例化
private List<Person> persons;
private Person person;
//创建一个缓冲区
private StringBuffer buffer=new StringBuffer();
@Override
publicvoid characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
buffer.append(ch, start, length);
Log.v("BUFFER", buffer.toString());
}
//解析文档结束
@Override
publicvoid endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
for (Person p:persons){
Log.v("P", p.toString());
}
Log.v("EDNDOC", "解析文档结束了");
}
@Override
publicvoid endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
if(localName.equals("person")){
persons.add(person);
}elseif(localName.equals("name")){
person.setName(buffer.toString().trim());
buffer.setLength(0);
}elseif(localName.equals("age")){
person.setAge(Integer.parseInt(buffer.toString().trim()));
buffer.setLength(0);
}
}
@Override
publicvoid endPrefixMapping(String prefix) throws SAXException {
// TODO Auto-generated method stub
}
@Override
publicvoid ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
}
@Override
publicvoid processingInstruction(String target, String data)
throws SAXException {
// TODO Auto-generated method stub
}
@Override
publicvoid setDocumentLocator(Locator locator) {
// TODO Auto-generated method stub
}
@Override
publicvoid skippedEntity(String name) throws SAXException {
// TODO Auto-generated method stub
}
//解析xml文档第一个触发的是startDocument方法
@Override
publicvoid startDocument() throws SAXException {
// TODO Auto-generated method stub
persons =new ArrayList<Person>();
Log.v("STARDOC", "解析文档开始----");
}
@Override
publicvoid startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, atts);
Log.v("ELEMENT", localName+"---"+qName+"--"+atts);
//当解析到person标签的时候实例化该person对象
if(localName.equals("person")){
person =new Person();
person.setId(Integer.parseInt(atts.getValue("id")));
}
}
@Override
publicvoid startPrefixMapping(String prefix, String uri)
throws SAXException {
// TODO Auto-generated method stub
}
}
使用Sax读取Xml文件
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button sax=(Button) findViewById(R.id.sax);
sax.setOnClickListener(new OnClickListener() {
@Override
publicvoid onClick(View v) {
// TODO Auto-generated method stub
//导入sdcard中 xml文件
//解析xml 文件
try {
FileInputStream fio=new FileInputStream(new File(
Environment.getExternalStorageDirectory(),
"persons.xml"
));
Saxxml contentHandler=new Saxxml();
android.util.Xml.parse(fio, Xml.Encoding.UTF_8,contentHandler);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
五.使用Dom读取XMl文件
除了可以使用 SAX解析XML文件,大家也可以使用熟悉的DOM来解析XML文件。 DOM解析XML文件时,会将XML文件的所有内容以对象树方式存放在内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。但是,因为DOM需要将XML文件的所有内容以对象树方式存放在内存中,所以内存的消耗比较大,特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM是可行的。
案例:public class DomXMLReader {
public static List<Person> readXML(InputStream inStream) {
List<Person> persons = new ArrayList<Person>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(inStream);
Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName("person");//查找所有person节点
for (int i = 0; i < items.getLength(); i++) {
Person person = new Person();
//得到第一个person节点
Element personNode = (Element) items.item(i);
//获取person节点的id属性值
person.setId(new Integer(personNode.getAttribute("id")));
//获取person节点下的所有子节点(标签之间的空白节点和name/age元素)
NodeList childsNodes = personNode.getChildNodes();
for (int j = 0; j < childsNodes.getLength(); j++) {
Node node = (Node) childsNodes.item(j);
//判断是否为元素类型
if(node.getNodeType() == Node.ELEMENT_NODE){ Element childNode = (Element) node;
//判断是否name元素
if ("name".equals(childNode.getNodeName())) {
//获取name元素下Text节点,然后从Text节点获取数据 person.setName(childNode.getFirstChild().getNodeValue());
} else if (“age”.equals(childNode.getNodeName())) {
person.setAge(new Short(childNode.getFirstChild().getNodeValue()));
}
}
}
persons.add(person);
}
inStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return persons;
}