文章出处: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(也就是全名)。明白了吧?
还有一点:关于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
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中的处理一模一样。