【Android知识点精讲】(11)数据解析

文章出处:http://blog.youkuaiyun.com/scarthr/article/details/42344129

一 XML SAX解析

解析XML文件有SAX、PULL、DOM3种方式。由于DOM解析是比较浪费资源的,在手机端不推荐使用,我们这里就不介绍了。我们这里详细介绍一下SAX解析方式。
SAX解析是一边读取文件一边解析的方式,所以是一种比较不耗资源的解析方式。
用SAX解析,我们要继承DefaultHandler类,实现它的4个主要方法:
package com.thr.testxmlsax;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MySaxParser extends DefaultHandler {

	private List<Book> bookList;
	private Book book;
	private String tag;

	public List<Book> getBooks() {
		return bookList;
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if ("name".equals(tag)) {
			book.setName(new String(ch, start, length));
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if ("book".equals(localName)) {
			bookList.add(book);
		}
		tag = null;
	}

	@Override
	public void startDocument() throws SAXException {
		bookList = new ArrayList<Book>();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if ("book".equals(localName)) {
			book = new Book();
			book.setId(Integer.parseInt(attributes.getValue(0)));
		}
		tag = localName;
	}

}
characters是在读取到xml文件标签外内容时执行的回调方法。
startDocument是开始读取xml文件的回调方法,我们在这里创建List集合
startElement是读取到一个标签开始节点的回调方法,每次在这个方法的结尾我们用一个tag来标记目前读取到的节点是什么。
endElement是读取到一个标签结束节点的回调方法。注意,在这个方法结束时,要将tag标签置空,负责他会记住上一个标签,并且读取到标签间隔中的空白字串时,会给上一个标签属性赋空值。
还有一点:关于localName、qName的解释,假如命名空间是local:blog的话,localName就是blog,qName就是local:blog(也就是全名)。明白了吧?
然后看怎么调用它:
//		try {
//			InputStream is = getResources().openRawResource(R.raw.books);
//			MySaxParser mySaxParser = new MySaxParser();
//			Xml.parse(is, Xml.Encoding.UTF_8, mySaxParser);
//			List<Book> bookList = mySaxParser.getBooks();
//			for (Book book : bookList) {
//				Log.i(TAG, book.toString());
//			}
//		} catch (IOException e) {
//			e.printStackTrace();
//		} catch (SAXException e) {
//			e.printStackTrace();
//		}

		try {
			InputStream is = getResources().openRawResource(R.raw.books);
			MySaxParser mySaxParser = new MySaxParser();
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			parser.parse(is, mySaxParser);
			List<Book> bookList = mySaxParser.getBooks();
			for (Book book : bookList) {
				Log.i(TAG, book.toString());
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
这里有两种方法都可以解析,用哪个都行。

二 JSON

Json是一种比Xml使用更多的网络数据传输格式,
读取Json数据:android.util.JsonReader
写入Json数据:android.util.JsonWriter
Json可以存数据和对象,先来看一个简单的Json数据:
[
	{
		"id":"01",
		"name":"第一"
	},
	{
		"id":"02",
		"name":"第二"
	}
]
最外层使用中括号包起来,里面每一个元素用大括号包起来,用逗号分隔。元素属性和值用冒号括起来,用冒号连接,每个属性用逗号分隔。

1. 写Json

这是一个写Json的例子:
package com.thr.testxmlsax;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.List;

import android.util.JsonWriter;

public class JsonWriterUtil {

	public void writeJson(File file, List<Book> bookList) throws IOException {
		FileOutputStream fos = new FileOutputStream(file);
		writeJsonStream(fos, bookList);
	}

	private void writeJsonStream(OutputStream out, List<Book> bookList)
			throws IOException {
		JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, "utf-8"));
		writer.setIndent("	");
		writeBookArray(writer, bookList);
		writer.close();
	}

	private void writeBookArray(JsonWriter writer, List<Book> bookList)
			throws IOException {
		writer.beginArray();
		for (Book book : bookList) {
			writeBook(writer, book);
		}
		writer.endArray();
	}

	private void writeBook(JsonWriter writer, Book book) throws IOException {
		writer.beginObject();
		writer.name("id").value(book.getId() + "");
		writer.name("name").value(book.getName());
		writer.endObject();
	}

}
用setIndent写代码间距,开始写json使用beginArray方法,结束用endArray,写一个元素的开始用beginObject,结束用endOgject。

2. 读Json

这是一个读Json的例子:
package com.thr.testxmlsax;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import android.util.JsonReader;

public class JsonReaderUtil {

	public List<Book> readJson(InputStream in) throws IOException {
		List<Book> bookList = new ArrayList<Book>();
		JsonReader reader = new JsonReader(new InputStreamReader(in));
		bookList = readBookArray(reader);
		reader.close();
		return bookList;
	}

	private List<Book> readBookArray(JsonReader reader) throws IOException {
		List<Book> bookList = new ArrayList<Book>();
		reader.beginArray();
		while (reader.hasNext()) {
			bookList.add(readBook(reader));
		}
		reader.endArray();
		return bookList;
	}

	private Book readBook(JsonReader reader) throws IOException {
		Book book = new Book();
		reader.beginObject();
		while (reader.hasNext()) {
			String field = reader.nextName();
			if ("id".equals(field)) {
				book.setId(Integer.parseInt(reader.nextString()));
			} else if ("name".equals(field)) {
				book.setName(reader.nextString());
			} else {
				reader.skipValue();
			}
		}
		reader.endObject();
		return book;
	}
}
这里注意在最后的readBook时候,需要定义一个field来存reader.nextName()的值,不然在同一个hasNext中,重复调用nextName是会报"Caused by: java.lang.IllegalStateException: Expected a name but was STRING"异常。
记住最后要加这两个权限:
    <!-- 往sdcard中写入数据的权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 在sdcard中创建/删除文件的权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

三 读写文件

读写文件的操作和Java中的益智,我们这里演示一个把资源图像文件写到SD卡中,然后在读取显示在ImageView中:
先是写文件的操作:
package com.thr.testxmlsax;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class FileUtil {

	public static void write2SDCard(InputStream in) throws IOException {
		File file = new File("/mnt/sdcard/test.jpg");
		file.createNewFile();
		FileOutputStream out = new FileOutputStream("/mnt/sdcard/test.jpg");
		byte[] buffer = new byte[1024];
		int count = 0;
		while ((count = in.read(buffer)) != -1) {
			out.write(buffer, 0, count);
		}
		out.close();
		in.close();
	}

	public static Bitmap read2ImageView() throws FileNotFoundException {
		FileInputStream in = new FileInputStream(new File(
				"/mnt/sdcard/test.jpg"));
		Bitmap bm = BitmapFactory.decodeStream(in);
		return bm;
	}
}
一个读文件,一个写文件,非常简单,和Java中的处理一模一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值