Android数据存储与访问(10级学员张晓丛)

一.     数据存储与访问

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

              //导入sdcardxml文件

             

              //解析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;

}

 

 

你可能感兴趣的:(xml,exception,android,String,Integer,存储)