Android中数据解析的五种方式

这里有一份XML文件,接下来我们用不同的解析方式来解析这份文件

<?xml version="1.0" encoding="UTF-8"?>
<Movies>
  <Movie id="1">
    <name>愤怒的小鸟</name>
    <type>Animation</type>
    <year>2016</year>
  </Movie>
  <Movie id="2">
    <name>叶问3</name>
    <type>Action</type>
    <language>English</language>
  </Movie>
</Movies>

1.DOM解析

//1.创建一个DocumentBuilderFactory对象
    DocumentBuilderFactory dBuilderFactory=DocumentBuilderFactory.newInstance();
    try {
      //2.创建一个DocumentBuilder对象
      DocumentBuilder dBuilder=dBuilderFactory.newDocumentBuilder();
      //3.获取Document对象
      Document document=dBuilder.parse("Movie.xml");
      System.out.println("解析开始:--------------------------");
      //获取Movie元素结点集合
      NodeList movies=document.getElementsByTagName("Movie");
      System.out.println("共有"+movies.getLength()+"部电影");
      //遍历Movie元素结点集合
      for(int i=0;i<movies.getLength();i++){
        System.out.println("=====================");
        System.out.println("正在解析"+(i+1)+"部电影!");
        Node movie=movies.item(i);
        //获取元素结点的属性集合
        NamedNodeMap attrs=movie.getAttributes();
        for(int j=0;j<attrs.getLength();j++){
          Node attr=attrs.item(j);
          System.out.print("属性名为:"+attr.getNodeName()+"    ");
          System.out.println("属性值为:"+attr.getNodeValue());
        }
        //获取movie元素子节点集合
        NodeList childNodes=movie.getChildNodes();
        for(int k=0;k<childNodes.getLength();k++){
          Node child=childNodes.item(k);
          if (child.getNodeType()==Document.ELEMENT_NODE) {
            System.out.println("节点名:"+child.getNodeName()+"    ");
            //System.out.println("节点值:"+child.getNodeValue());
            System.out.println("节点值:"+child.getFirstChild().getNodeValue());
          }
        }
        System.out.println("第"+(i+1)+"部电影解析结束");
      }
      System.out.println("解析结束--------------------------------");
    } catch (Exception e) {
      e.printStackTrace();
    }

2.SAX解析

//1.创建SAXFactory对象
    SAXParserFactory sParserFactory=SAXParserFactory .newInstance();
    //2.拿到一个SAXParser解析对象
    try {
      SAXParser saxParser=sParserFactory.newSAXParser();
      saxParser.parse("Movie.xml",new MyHandler() );
    } catch (Exception e) {
      e.printStackTrace();
    }

接下来需要写一个类去继承DefaultHandler,然后一般要重写里面的五个方法:

1)startDocument(),该方法一执行表示解析开始,可以在里面去初始化对象集合

@Override
  public void startDocument() throws SAXException {
    System.out.println("开始解析----------------------------");
    movieList=new ArrayList<>();
  }

2)startEnement(),该方法一执行表示解析到了开始元素,亦即xml文件里面的Movie标签

@Override
  public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    //
    if ("Movie".equals(qName)) {
      movie=new Movie();
      count++;
      System.out.println("正在解析第"+count+"部电影!");
      for (int i = 0; i < attributes.getLength(); i++) {
        //拿到属性名和属性值
        System.out.print("属性名:"+attributes.getQName(i)+"    ");
        System.out.println("属性值:"+attributes.getValue(i));
        if (attributes.getQName(i).equals("id")) {
          movie.setMovieId(attributes.getValue(i));
        }
      }
    }
  }

3)characters(),在该方法里面去读取元素的值

@Override
  public void characters(char[] ch, int start, int length) throws SAXException {
    value=new String(ch,start,length);
    if (!value.trim().equals("")) {
      System.out.println("节点值:"+value);
    }
  }

4)endElement(),表示解析到了一个元素的结束标签,在该方法里面可以去 构造对象,最后并且添加到集合里去

@Override
  public void endElement(String uri, String localName, String qName) throws SAXException {
    if (qName.equals("year")) {
      movie.setMovieYear(value);
    }
    if (qName.equals("type")) {
      movie.setMovieType(value);
    }
    if (qName.equals("language")) {
      movie.setMovieLanguage(value);
    }
    if (qName.equals("name")) {
      movie.setMovieName(value);
    }
    //解析完一个元素时回调
    if ("Movie".equals(qName)) {
      movieList.add(movie);
      movie=null;
      System.out.println("第"+count+"部电影解析结束!");
    }
  }

5)endDocument(),当执行到该方法也就表示文件已经解析完毕了

@Override
  public void endDocument() throws SAXException {
    System.out.println("解析结束----------------------------");
    System.out.println("解析结果集如下:");
    for(int i=0;i<movieList.size();i++){
      System.out.println(movieList.get(i).toString());
      System.out.println("----------------------------------");
    }
  }

3.PULL解析

pull解析与其它方式不同的是,它需要将xml文件存放在资源文件res下面的xml文件夹下,解析的过程如下:

1)首先拿到一个Pull资源解析器,有时如果通过网络上下载xml文件的话,则需要去构造一个Pull解析器,再将流设置给pull解析器, 接下来就是一样的,一个标签一个标签的去解析

//拿到一个XMLResourceParser
    //XmlPullParser parser=Xml.newPullParser();
    //parser.setInput(in);
    XmlResourceParser xmlResourceParser=getResources().getXml(R.xml.movie);
    //拿到第一个事件类型,也就是最外层的标签
    try {
      int type=xmlResourceParser.getEventType();
      while(type!=XmlResourceParser.END_DOCUMENT){
        if (type==XmlResourceParser.START_DOCUMENT) {
          System.out.println("开始解析");
          movieList=new ArrayList<>();
        }
        if (type==XmlResourceParser.START_TAG) {
          if ("Movie".equals(xmlResourceParser.getName())) {
            movie=new Movie();
            String id=xmlResourceParser.getAttributeValue(null, "id");
            System.out.println("id:"+id);
            movie.setMovieId(id);
          }
          if ("name".equals(xmlResourceParser.getName())) {
            //System.out.println("name:"+xmlResourceParser.nextText()+"===========");
            movie.setMovieName(xmlResourceParser.nextText());
          }else if ("type".equals(xmlResourceParser.getName())) {
            movie.setMovieType(xmlResourceParser.nextText());
          }else if ("year".equals(xmlResourceParser.getName())) {
            movie.setMovieYear(xmlResourceParser.nextText());
          }else if ("language".equals(xmlResourceParser.getName())) {
            movie.setMovieLanguage(xmlResourceParser.nextText());
          }
        }
        if (type==XmlResourceParser.END_TAG) {
          if ("Movie".equals(xmlResourceParser.getName())) {
            movieList.add(movie);
            movie=null;
          }
        }
        type=xmlResourceParser.next();
      }
      System.out.println("解析结束");
      StringBuffer sBuffer=new StringBuffer();
      for (int i = 0; i < movieList.size(); i++) {
        sBuffer.append(movieList.get(i).toString())
        .append("\n");
      }
      show_tv.setText(sBuffer.toString());
    } catch (Exception e) {
      e.printStackTrace();
    }

4.Json解析

Json解析的话需要先给出一份JSon数据,就拿下面的数据来解析吧!

private static final String JSONDATA="{name:张三,"
      + "age:26,"
      + "phone:[131,132],"
      + "score:{"
      + "语文:100,"
      + "数学:90,"
      + "理综:{化学:80,物理:70,生物:80}}}";

Json解析的过程无疑就是碰到大括号,就new一个Object出来,中括号就new一个Array出来,再用一个for循环去读取数据:

StringBuffer stringBuffer=new StringBuffer();
    try {
      //JSONObject jsonObject=new JSONObject(JSONDATA);
      JSONTokener jsonTokener=new JSONTokener(JSONDATA);
      JSONObject jsonObject=(JSONObject) jsonTokener.nextValue();
      stringBuffer.append("name:"+jsonObject.getString("name")+"\n");
      stringBuffer.append("aeg:"+jsonObject.getString("age")+"\n");
      JSONArray phoneArray=jsonObject.getJSONArray("phone");
      stringBuffer.append("phone:"+phoneArray.getString(0)
                      +"  "+phoneArray.getString(1)+"\n");
      JSONObject scoreJsonObject=jsonObject.getJSONObject("score");
      stringBuffer.append("语文:"+scoreJsonObject.getString("语文")+"\n")
      .append("数学:"+scoreJsonObject.getString("数学"));
      JSONObject lizongObject=scoreJsonObject.getJSONObject("理综");
      stringBuffer.append("化学:"+lizongObject.getString("化学")+"\n")
      .append("物理:"+lizongObject.getString("物理")+"\n")
      .append("生物:"+lizongObject.getString("生物"));
      show_tv.setText(stringBuffer.toString());
    } catch (Exception e) {
      e.printStackTrace();
    }

5.GSON解析

GSON解析相对来说简单一些,但也有一定的局限性,比如说,数据类的属性字段和key值必须是一一对应的

//拿GSON去解析数据时,数据类的属性值跟key值必须是对应的
    Gson gson=new Gson();
    Student student=gson.fromJson(JSONDATA, Student.class);

数据类的属性:

public String name;
public String age;
public ArrayList<String> phone=new ArrayList<>();
public ArrayList<Score> score=new ArrayList<>();
public class Score{
  public String id;
  public String fenshu;
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • Android可自定义神奇动效的卡片切换视图实例

    前言 面对众多卡片层叠效果,我们的产品童鞋也突发奇想,搞出了另一种卡片层叠切换展示的交互,而且产品狗们居然要求多做几种动效给他们看,好让他们选择,这简直就是要搞事情啊,what are you 弄啥咧?! "哥哥我做不到啊.....啊.....呸",做为一名有节操的程序猿,自然是不能说出这么没有出息的话,哥就满足你们,于是,出了个可自定义动效的卡片切换视图,效果如下所示 思路 首先,要展示出卡片层叠的视觉效果.在这里,我们通过方块的缩放大小差异以及在Y方向上的位置差异,来展现这种视觉效

  • Android手机获取Mac地址的几种方法

    最常用的方法,通过WiFiManager获取: /** * 通过WiFiManager获取mac地址 * @param context * @return */ private static String tryGetWifiMac(Context context) { WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); WifiInfo wi

  • Android四大组件之Service详解

    一.Service简介 Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有UI界面,是在后台运行的组件. Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务.Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作. 二.Serv

  • Android Java调用自己C++类库的实例讲解

    Android Java 如何调用自己的 C++ 的类库 下面以 Java 调用 C++ 的加法运算函数为例,做简单说明. (使用 Android Studio 3 编译) 首先编译 c++ 类库 创建独立目录存放 c++ 文件,例如 "app/src/main/cpp/add.cpp",内容如下 #include <jni.h> extern "C" JNIEXPORT jint JNICALL Java_com_example_liyi_demo_U

  • Android之在linux终端执行shell脚本直接打印当前运行app的日志的实现方法

    1.问题 我们一般很多时候会需要在ubuntu终端上打印当前运行app的日志,我们一般常见的做法是 1).获取包名 打开当前运行的app,然后输入如下命令,然后在第一行TASK后面的就可以看到包名 adb shell dumpsys activity top 2).我们的终端安装了pidcat.py脚本,然后执行如下的命令就可以打印当前运行app的全日志, pidcat.py packageName 3).思考,为什么每次都需要这样重复的操作呢?一说到重复,我们应该立马想到是否可以用脚本解决重复

  • Android获取当前应用分配的最大内存和目前使用内存的方法

    在Android里,程序内存被分为2部分:native和dalvik,dalvik就是我们普通的Java使用内存,分析堆栈的时候使用的内存.我们创建的对象是在这里面分配的,对于内存的限制是 native+dalvik 不能超过最大限制. Android 原生系统一般默认16M,但是国内手机一般都是特殊定制的,都有修改系统的内存大小,所有有时候,要查看具体应用系统分配的内存大小,还是需要实际去测试的, 测试方法如下: 方式一: ActivityManager activityManager = (

  • Android亮屏速度分析总结

    前面聊的 最近在调试项目的亮屏速度,我们希望在按下power键后到亮屏这个时间能达到500MS以内,在Rockchip 3399和3288上面的时间都不能达到要求,因此引发了一系列的调试之路. 计算按下power键到亮屏的时间 Android 唤醒时间统计 刚开始的时候,我只在android阶段统计时间,也能看到时间的差异,但是不是最准确的,我统计的时间日志如下 01-18 09:13:40.992 683 772 D SurfaceControl: Excessive delay in set

  • Android线程中Handle的使用讲解

    Android UI线程是不安全的,子线程中进行UI操作,可能会导致程序的崩溃,解决办法:创建一个Message对象,然后借助Handler发送出去,之后在Handler的handleMessage()方法中获得刚才发送的Message对象,然后在这里进行UI操作就不会再出现崩溃了 定义类继承Handler public class BallHandler extends Handler{ ImageView imageview; Bitmap bitmap; public BallHandle

  • Android添加音频的几种方法

    在res文件夹中新建一个文件夹,命名为raw.在里面放入我们需要的音频文件. 第一种: // 根据资源创建播放器对象 player = MediaPlayer.create(this, R.raw.xiaoxiaole); try { player.prepare();// 同步 } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOExcept

  • Android调试神器stetho使用详解和改造

    概述 stetho是Facebook开源的一个Android调试工具,项目地址:facebook/stetho 通过Stetho,开发者可以使用chrome的inspect功能,对Android应用进行调试和查看. 功能概述 stetho提供的功能主要有: Network Inspection:网络抓包,如果你使用的是当前流行的OkHttp或者Android自带的 HttpURLConnection,你可以轻松地在chrome inspect窗口的network一栏抓到所有的网络请求和回包,还用

随机推荐