原文http://www.eoeandroid.com/blog-498208-2757.html
一个私人项目要求数据存储在xml中,跟着大众走选择sax解析。
但是问题来了。sax貌似不支持中文,关键客户提供的xml编码不清楚。经过长时间的google,最后选择开源项目CodepageDetector。步奏什么挺简单的,在网上一大把,但是还是贴下代码。
EncodingUtil.java 就一个静态方法
public static String checkEncoding(URL url) {
String encodingName = null;
CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
detector.add(new ParsingDetector(false));
detector.add(JChardetFacade.getInstance());
detector.add(ASCIIDetector.getInstance());
detector.add(UnicodeDetector.getInstance());
Charset charset = null;
try {
charset = detector.detectCodepage(url);
} catch (IOException e) {
e.printStackTrace();
}
encodingName =charset.name();
return encodingName;
}
还一个关键的类BClassContentHandler.java 将大概写下
public class BClassContentHandler extends DefaultHandler {
public static final String TSM_BCLASS_ROW = "你的xml结点";
public static final String TSM_BCLASS_ROW1 = "你的xml结点";
private String tagName = "";
private List<你的类> 你要返回的值;
private 你的类 classValue;
public List<你的类> getListBClassRow() {
return 你要返回的值;
}
@Override
public void startDocument() throws SAXException {
你要返回的值 = new ArrayList<你的类>();
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
tagName = localName;
if (TSM_BCLASS_ROW1.equals(tagName)) {
classValue = new 你的结点类();
}
//super.startElement(uri, localName, qName, attributes);
}
public void characters(char[] ch, int start, int length)
throws SAXException {
if (bClassRow != null) {
if (tagName.equals(TSM_BCLASS_ROW1)) {
String tem = new String(ch, start, length);
classValue.setTer(tem);
} else if (tagName.equals(xml结点名)) {
..................
}
}
// super.characters(ch, start, length);
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (TSM_BCLASS_ROW.equals(localName)) {
你要返回的值.add(classValue);
bClassRow = null;
}
//super.endElement(uri, localName, qName);
}
写的时候有点麻烦。但是细心点发现还是很好理解的。
下面是网上说的很多的sax解析,随便创建个类,写个方法提供调用的:
SAXBClassService。java
public static List<Tsm_bclass_row> readXml(InputSource inStream)
throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser(); // 创建解析器
BClassContentHandler handler = new BClassContentHandler();
saxParser.parse(inStream, handler);
return handler.getListBClassRow();
}
最后就是在你要处理的地方来调用之前的哪些类和方法了。
private void getFromSDCard(String name){
// 获取扩展SD卡设备状态
String sDStateString = android.os.Environment.getExternalStorageState();
// 拥有可读可写权限
if (sDStateString.equals(android.os.Environment.MEDIA_MOUNTED)) {
// 获取扩展存储设备的文件目录
File SDFile = android.os.Environment.getExternalStorageDirectory();
// 打开文件
File xmlFile = new File(SDFile.getAbsolutePath() + File.separator + name);
// 判断文件是否存在
URL url;
InputSource is=null;
InputStream stream = null;
if (xmlFile.exists()) {
try {
url = xmlFile.toURI().toURL();
if("GBK".equals(EncodingUtil.checkEncoding(url))){
stream = url.openStream();
InputStreamReader streamReader = new InputStreamReader(stream,"GBK");
is = new InputSource(streamReader);
}else{
is = new InputSource(url.openStream());
is.setEncoding("UTF-8");
}
和上面一样,你返回的值 = SAXBClassService.readXml(is);
System.out.println("---------" + listBClassRow + "---------");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
到这里代码部分基本结束了,但是是开源项目就涉及到附件中的3个jar包了。
但是将jar直接build还是不行的,会在你的CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
这个地方报错的:java.lang.NoClassDefFoundError: info.monitorenter.cpdetector.io.CodepageDetectorProxy
怎么解决了简单:
在工程下建个lib目录,将3个jar包放在里面,并且build之后,在eclips的工程上右击 选择properties --java build path ---在右边窗口选择第一个 source 将lib目录设为源文件夹。这样你的工程基本就好了,没有问题了。
PS:不知道怎么上传附件,cpdetector_1.0.7.jar下载这个包就可以,有3个依赖包。