1.数据格式的引入
在开发应用程序的时候经常性的会遇到服务器与客户端通讯,或者不同语言间数据传递与交互的情况。就这样人们就总结出了统一的数据格式来传递数据,这就是数据格式或叫做数据交换格式。
常见的数据交换格式有:
- XML
- JSON
2.XML数据格式简介
XML:可扩展标记语言(Extensible Markup Language XML),用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML是标准通用标记语言(SGML)的子集,非常适合Web传输,XML提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。
XML和HTML或其他语言最大的区别是:XML是用来存储数据的。
XML的语言:
任何的起始标签都必须有一个结束标签。
可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟着一个斜线(/),例如.XML解析器会将其翻译成
标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签。
所有的属性都必须有值。
所有的属性都必须在值的周围加上双引号。
举例:
<?xml version="1.0" encoding="utf-8" ?> <employees> <employee id="1"> <name>张三</name> <gender>男</gender> <address> <homeaddress>河北省邯郸市</homeaddress> <workaddress>河北省石家庄市</workaddress> </address> </employee> <employee id="2"> <name>李四</name> <gender>女</gender> <address> <homeaddress>河北省保定市</homeaddress> <workaddress>河北省张家口市</workaddress> </address> </employee> </employees>
XML的特点:
1.XML被设计用来结构化存储以及传输信息。
2.XML仅仅是纯文本。
3.XML可自定义标签
4.XML和HTML不可相互替代
5.XML是W3C的推荐标准。
6.XML无所不在。
3.解析XML数据的方法
3.1DOM方式解析
特点:
先把XML文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据。
一次全部加载,如果对于数据量小的情况下,它的效率还可以,如果XML文件很大的情况下。速度就会慢起来。
直接把文档调入内存中,比较耗内存。
步骤:
private void parseStudents() throws ParserConfigurationException, IOException, SAXException { // 1.首先利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 2.然后利用DocumentBuilderFactory创建DocumentBuilder; DocumentBuilder builder = factory.newDocumentBuilder(); // 3.然后加载XML文档(Document); InputStream is = getAssets().open("students.xml"); Document document = builder.parse(is);//读取xml文件,生成DOM树 // 4.然后获取文档的根结点(Element); Element root = document.getDocumentElement();//获取根节点 Log.e("根节点的名称", root.getTagName()); // 5.然后获取根结点中所有子节点的列表(NodeList); NodeList studentList = root.getChildNodes(); // 6.然后再获取子节点列表中的需要读取的结点。 List<Student> students = new ArrayList<>(); for (int i = 0; i < studentList.getLength(); i++) { Student student = new Student(); Node stuNode = studentList.item(i);//遍历NodeList,获取结点列表中每一个结点 Log.e("stuNode标签", stuNode.getNodeName()); NamedNodeMap map = stuNode.getAttributes();//获取该节点的所有属性 if (stuNode.getNodeName().equals("student")) { Node genderNode = map.getNamedItem("gender");//将某一个属性转换成一个node对象 String gender = genderNode.getTextContent();//获取节点的值 student.setGender(gender);//为student的属性赋值 //获取student节点的子节点列表 NodeList childList = stuNode.getChildNodes(); for (int j = 0; j < childList.getLength(); j++) { Node childNode = childList.item(j); if (childNode.getNodeName().equals("name")) { String name = childNode.getTextContent(); student.setName(name); } else if (childNode.getNodeName().equals("nickname")) { String nickname = childNode.getTextContent(); student.setNickname(nickname); } } students.add(student); } }
3.2 SAX解析方式
特点:
SAX即是:Simple API for XML.
SAX是基于事件驱动的。当然Android的事件机制是基于回调函数的,在用SAX解析XML文档时候,在读到文档开始和结束标签时候就会回调一个事件,在读到其他节点于内容时候也会回调一个事件。
步骤:
public class ParseBySAX { private Context context; private List<Student> students; public ParseBySAX(Context context) { this.context = context; } //通过SAX方式解析XML文件 public List<Student> getStudents() throws ParserConfigurationException, SAXException, IOException { // 创建SAXParserFactory对象。 SAXParserFactory factory = SAXParserFactory.newInstance(); // 根据SAXParserFactory.newSAXParser()方法返回一个SAXParser解析器。 SAXParser parser = factory.newSAXParser(); //根据SAXParser解析器获取事件源对象XMLReader。 XMLReader reader = parser.getXMLReader(); //实例化一个DefaultHandler对象。 MyDefaultHandler myDefaultHandler = new MyDefaultHandler(); //连接事件源对象XMLReader到事件处理类DefaultHandler。 reader.setContentHandler(myDefaultHandler);//绑定解析文档内容的处理器 //调用XMLReader的parse方法从输入源中获取xml数据。 InputStream inputStream = context.getAssets().open("students.xml"); reader.parse(new InputSource(inputStream)); // 通过DefaultHandler返回我们需要的数据集合。 return students; } //解析XML时产生的事件处理器类 private class MyDefaultHandler extends DefaultHandler { private String content; private Student student; //文件解析开始事件 @Override public void startDocument() throws SAXException { super.startDocument(); students = new ArrayList<>(); Log.e("sax", "解析到文档开始"); } //开始标签 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); student = new Student(); Log.e("sax", "解析到开始标签" + localName); if (localName.equals(students)) { String gender = attributes.getValue("gender"); student.setGender(gender); } } //标签内容 @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); content = new String(ch, start, length); Log.e("sax", "标签内容" + content);//没有办法区别标签内容 } //结束标签 @Override public void endElement(String uri, String localName, String qName) throws SAXException {//这里区分标签内容 super.endElement(uri, localName, qName); Log.e("sax", "解析到结束标签"); if (localName.equals("name")) {//证明存储到content中的数据是姓名 student.setName(content); } else if (localName.equals("nickname")) { student.setNickname(content); } else if (localName.equals("student")) { students.add(student); } } //文档末尾 @Override public void endDocument() throws SAXException { super.endDocument(); Log.e("sax", "解析到文档末尾"); Log.e("解析到的数据", students.toString()); } } }
3.3 PULL解析方式
步骤:
private List<Student> parseByPULL() throws IOException, XmlPullParserException { List<Student> students = new ArrayList<>(); //创建XMLPULLParse对象 XmlPullParser pullParser = Xml.newPullParser(); //初始化XmlPullParser(设置Xml文件的输入流对象) InputStream inputStream = getAssets().open("students.xml"); pullParser.setInput(inputStream, "UTF-8"); //开始解析,并且返回一个事件类型 int type = pullParser.getEventType(); Student student = null; //判断事件类型不是文档末尾 while (type != XmlPullParser.END_DOCUMENT) { switch (type) { case XmlPullParser.START_DOCUMENT: //文档开始 break; case XmlPullParser.START_TAG: //解析到开始标签(获取到标签的属性和内容) String tagName = pullParser.getName();//获取标签的名称 Log.e("pull", tagName); if (tagName.equals("student")) { String gender = pullParser.getAttributeValue(null, "gender"); student = new Student(); student.setGender(gender); } else if (tagName.equals("name")) { //获取标签的内容 String name = pullParser.nextText(); student.setName(name); } else if (tagName.equals("nickname")) { String nickname = pullParser.nextText(); student.setNickname(nickname); } break; case XmlPullParser.END_TAG://结束标签 //解析到结束标签 if (pullParser.getName().equals("student")) { students.add(student); } else if (pullParser.getName().equals("students")) { Log.e("解析结果", students.toString()); } break; } //继续解析下一个事件类型 type = pullParser.next(); } return students;
4.JSON数据格式简介
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。
JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从客户端传递给服务器端程序。这个字符串看起来有点儿古怪,但是 JavaScript 很容易解释它,而且 JSON 可以表示比"名称 / 值对"更复杂的结构。例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表。
JSON基本的结构有两种:
“名称/值”对的集合(a collection of name/value pairs)。不同的语言中,它被理解为对象(object),记录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
值的有序列表(an ordered list of values)。在大部分语言中,它被理解为数组(array)
5.解析JSON数据的方法
1.把用户对象的数据转换成JSON格式的字符串
public String object2JSON(User user) throws JSONException { JSONObject jsonObject=new JSONObject(); jsonObject.put("username",user.getUserName()); jsonObject.put("password",user.getPassWord()); return jsonObject.toString(); }
2.把JSON格式的字符串转换成用户对象
public User json2Object(String jsonStr) throws JSONException { User user=new User(); JSONObject jsonObject=new JSONObject(jsonStr); user.setUserName(jsonObject.getString("username")); user.setPassWord(jsonObject.getString("password")); return user; }