一直以来对于数据使用的都是JSON格式,对于xml只是略有了解,而我们一直以来使用的sharedpreference就是xml文件,于是作者撸了一发xml数据的存储。
/**
* Created by xuwx on 2017/5/5.
*/
public class XmlParseHelper {
private String xmlName;
private String mXmlPath;
private static List<Map<String, Map<String, XmlBean>>> parserList = new ArrayList<>();
public XmlParseHelper(String xmlName, Context context) {
this.xmlName = xmlName;
mXmlPath = PathUtil.getInstance(context).getPrivateXmlDirectory();
}
public void setXmlPath(String path) {
mXmlPath = path;
}
/**
* 获取所有保存的字段的名字
*
* @return
*/
public List<String> getKeyList() {
Map<String, XmlBean> keyValues = null;
List<String> keyList = null;
try {
keyValues = parser();
keyList = new ArrayList<>(keyValues.keySet());
} catch (Exception e) {
e.printStackTrace();
}
return keyList;
}
/**
* 获取所有保存的值
*
* @return
*/
public List<XmlBean> getValueList() {
Map<String, XmlBean> keyValues = null;
List<XmlBean> valueList = null;
try {
keyValues = parser();
valueList = new ArrayList<>(keyValues.values());
} catch (Exception e) {
e.printStackTrace();
}
return valueList;
}
/**
* 从xml文件解析出所有数据
*
* @return 以map形式展示
* @throws FileNotFoundException
*/
public Map<String, XmlBean> parser() throws Exception {
Map<String, XmlBean> keyValues = new HashMap<>();
try {
if (mXmlPath == null) {
return null;
}
/** 加入缓存优化性能*/
for (Map<String, Map<String, XmlBean>> parser : parserList) {
if (parser.containsKey(xmlName)) {
return parser.get(xmlName);
}
}
String path = mXmlPath + "/" + xmlName + ".xml";
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
return keyValues;
}
FileInputStream inputStream = new FileInputStream(file);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(inputStream, "utf-8");
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagName = parser.getName();
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
if ("string".equals(tagName)) {
XmlBean xmlBean = new XmlBean();
String key = parser.getAttributeValue(null, "name");
xmlBean.setTypeName(tagName);
xmlBean.setValue(parser.nextText());
if (!TextUtils.isEmpty(key)) {
keyValues.put(key, xmlBean);
}
}
if ("long".equals(tagName) || "boolean".equals(tagName) || "int".equals(tagName)) {
XmlBean xmlBean = new XmlBean();
xmlBean.setTypeName(tagName);
xmlBean.setValue(parser.getAttributeValue(null, "value"));
String key = parser.getAttributeValue(null, "name");
if (!TextUtils.isEmpty(key)) {
keyValues.put(key, xmlBean);
}
}
break;
case XmlPullParser.END_TAG:
break;
case XmlPullParser.TEXT:
break;
default:
break;
}
eventType = parser.next();//重新赋值,不然会死循环
}
Map<String, Map<String, XmlBean>> parserInstance = new HashMap<>();
parserInstance.put(xmlName, keyValues);
parserList.add(parserInstance);
} catch (Exception e) {
e.printStackTrace();
}
return keyValues;
}
public long getLong(String key, long defaultValue) {
try {
XmlBean value = (XmlBean) getValueFromXml(key);
return value == null ? defaultValue : (Long) value.getValue();
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
public String getString(String key, String defaultValue) {
try {
XmlBean value = (XmlBean) getValueFromXml(key);
return value == null ? defaultValue : (String) value.getValue();
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
public int getInt(String key, int defaultValue) {
try {
XmlBean value = (XmlBean) getValueFromXml(key);
return value == null ? defaultValue : (Integer) value.getValue();
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
public boolean getBoolean(String key, boolean defaultValue) {
try {
XmlBean value = (XmlBean) getValueFromXml(key);
return value == null ? defaultValue : (Boolean) value.getValue();
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
public Object getValueFromXml(String key) {
if (TextUtils.isEmpty(key)) {
return null;
}
Map<String, XmlBean> dataMap;
try {
dataMap = parser();
if (dataMap == null) {
return null;
}
return dataMap.get(key);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/** 换行美化格式*/
private void changeLine(XmlSerializer xmlSerializer, String enter) {
try {
xmlSerializer.text(enter);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 存储数据
*
* @param key 字段名
* @param value 字段值
* @param typeName 字段类型
*/
public void putValue2Xml(String key, Object value, String typeName) {
FileOutputStream fos = null;
try {
if (TextUtils.isEmpty(key)) {
return;
}
if (value == null) {
value = "";
}
if (TextUtils.isEmpty(typeName)) {
typeName = String.class.getSimpleName();
}
typeName = typeName.toLowerCase();
synchronized (this) {
XmlSerializer serializer = Xml.newSerializer();
Map<String, XmlBean> preDataMap = parser();
if (preDataMap == null) {
preDataMap = new HashMap<>();
}
XmlBean xmlBean = new XmlBean();
xmlBean.setValue(value);
xmlBean.setTypeName(typeName);
preDataMap.put(key, xmlBean);
List<Map.Entry<String, XmlBean>> entryList = new ArrayList<>(preDataMap.entrySet());
fos = new FileOutputStream(mXmlPath + "/" + xmlName + ".xml");
serializer.setOutput(fos, "UTF-8");
serializer.startDocument("UTF-8", true);
/** 换行符号*/
String enter = System.getProperty("line.separator");
changeLine(serializer, enter);
serializer.startTag("", "map");
changeLine(serializer, enter);
for (Map.Entry<String, XmlBean> keyValue :
entryList) {
if (typeName.equalsIgnoreCase("string")) {
serializer.startTag("", keyValue.getValue().getTypeName());
serializer.attribute("", "name", keyValue.getKey());
serializer.text(String.valueOf(keyValue.getValue().getValue()));
serializer.endTag("", keyValue.getValue().getTypeName());
} else {
serializer.startTag("", keyValue.getValue().getTypeName());
serializer.attribute("", "name", keyValue.getKey());
serializer.attribute("", "value", String.valueOf(keyValue.getValue().getValue()));
serializer.endTag("", keyValue.getValue().getTypeName());
}
}
serializer.endTag("", "map");
serializer.endDocument();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
下面是PathUtil类
/**
* Created by xuwx on 2017/5/31 0031.
*/
public class PathUtil {
private static PathUtil mInstance;
private Context mContext;
public final String PUBLIC_DIRECTORY = "/.xmlUtil";
private String mPrivateDirectory = "";
private String mPublicDirectory = "";
private final String XML_DIRECTORY = "xml";
public static PathUtil getInstance(Context context) {
if (mInstance == null) {
synchronized (PathUtil.class) {
if (mInstance == null) {
mInstance = new PathUtil(context);
}
}
}
return mInstance;
}
public PathUtil(Context mContext) {
this.mContext = mContext;
}
private String getPrivateDirectory() {
if (!TextUtils.isEmpty(mPrivateDirectory)) {
return mPrivateDirectory;
}
File appPrivateFile = mContext.getFilesDir();
File file = new File(appPrivateFile.getAbsolutePath());
if (!file.exists()) {
return "";
}
File parent = file.getParentFile();
if (!parent.exists()) {
return "";
}
mPrivateDirectory = parent.getAbsolutePath();
return mPrivateDirectory;
}
private String getPublicDirectory() {
if (!TextUtils.isEmpty(mPublicDirectory)) {
return mPublicDirectory;
}
String status = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(status)) {
return "";
}
String path = Environment.getExternalStorageDirectory() + PUBLIC_DIRECTORY;
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
mPublicDirectory = path;
return mPublicDirectory;
}
public String getPrivateXmlDirectory() {
String path = getDirectory(getPrivateDirectory(), XML_DIRECTORY);
if (path == null) {
mPrivateDirectory = "";
path = getDirectory(getPrivateDirectory(), XML_DIRECTORY);
}
return path;
}
public String getPublicXmlDirectory() {
String path = getDirectory(getPublicDirectory(), XML_DIRECTORY);
if (path == null) {
mPublicDirectory = "";
path = getDirectory(getPublicDirectory(), XML_DIRECTORY);
}
return path;
}
private String getDirectory(String root, String directory) {
if (TextUtils.isEmpty(root)) {
return "";
}
String path = root + "/" + directory;
File file = new File(path);
if (!file.exists()) {
boolean isSuccess = file.mkdir();
if (!isSuccess) {
return null;
}
}
return path;
}
}
整体实现思路比较简单,存储格式完全是模仿sharedpreference,需要注意的是在文件操作时进行同步以及优化避免出现数据读取出错的问题。