1

我一直在寻找一种快速简单的方法来解析包含数据元素和属性的自定义 XML 文件,如下所示:

<book>
    <book type="sci-fi">
    <book cost="25">
</book>

除此之外,我将有一个包含这些元素的书籍类。而且很简单,我可以创建一个 XML:文件读取书籍类并将其转换为 XML。并且还能够读取 XML 并转换为新的书籍类。

所以我发现了这个东西

其中包括以下几行:

Serializer serializer = new Persister();
Example example = new Example("Example message", 123);
File result = new File("example.xml");

serializer.write(example, result);

我可以在 Android 应用程序中使用这些功能吗?序列化器和持久化器?或者它被称为有什么不同?

4

2 回答 2

1

我认为您想将一个对象保存到本地文件中。

是的,在 android 中你可以使用 ObjectOutputStream 类来编写 Object(writeObject 方法),并使用 ObjectOutputStream 保存到文件中。对应的读取函数类是ObjectInputStream。但是,最重要的是你要保存的类对象必须实现 Serializable 接口

于 2012-08-02T08:49:29.267 回答
0

您可以使用 Android 附带的 XML 解析器。参考

public List parse(InputStream in) throws XmlPullParserException, IOException {
    try {
        XmlPullParser parser = Xml.newPullParser();
        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
        parser.setInput(in, null);
        parser.nextTag();
        return readFeed(parser);
    } finally {
        in.close();
    }
}

这将返回解析器,并返回数据。InputStream 是您从中读取的流。

此外,这是从 android 文档复制的示例,并添加了说明:

private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
    List entries = new ArrayList();

    parser.require(XmlPullParser.START_TAG, ns, "feed");//We read the parser inputted, but we try to find a specific tag. This can be the base tag, or if you have multiple of the same type, get the first.
    while (parser.next() != XmlPullParser.END_TAG) {//As long as the parser doesn't detect an end tag
        if (parser.getEventType() != XmlPullParser.START_TAG) {//and it isn't a start tag
            continue;
        }
        String name = parser.getName();//we parse the tag found by the reader
        //Then there are if-statements to determine what type of tag it is. This example uses a specific type to look for, as this looks for <entry>
        if (name.equals("entry")) {
            entries.add(readEntry(parser));//If it is that tag, add it to the list of content
        } else {
            skip(parser);//else skip it
        }
    }
    return entries;
}

此外,这可以应用于创建类:

一、入门类

public static class Entry {
    public final String title;
    public final String link;
    public final String summary;

    private Entry(String title, String summary, String link) {
        this.title = title;
        this.summary = summary;
        this.link = link;
    }
}

然后解析:

// Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off
// to their respective "read" methods for processing. Otherwise, skips the tag.
private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException {
    parser.require(XmlPullParser.START_TAG, ns, "entry");//finds the children of the tag "entry"
    String title = null;
    String summary = null;
    String link = null;
    while (parser.next() != XmlPullParser.END_TAG) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }
        //and using if-statements, we find the different types of tags, and distribute the content to the appropriate strings
        String name = parser.getName();
        if (name.equals("title")) {
            title = readTitle(parser);
        } else if (name.equals("summary")) {
            summary = readSummary(parser);
        } else if (name.equals("link")) {
            link = readLink(parser);
        } else {
            skip(parser);
        }
    }
    //And finally, we create a new entry
    return new Entry(title, summary, link);
}

//The following methods are the methods used to parse the different tags. 
//They are used as separate methods to make it more clear what goes where, 
//instead of pushing all these into the same method
// Processes title tags in the feed.
private String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {
    parser.require(XmlPullParser.START_TAG, ns, "title");
    String title = readText(parser);
    parser.require(XmlPullParser.END_TAG, ns, "title");
    return title;
}

// Processes link tags in the feed.
private String readLink(XmlPullParser parser) throws IOException, XmlPullParserException {
    String link = "";
    parser.require(XmlPullParser.START_TAG, ns, "link");
    String tag = parser.getName();
    String relType = parser.getAttributeValue(null, "rel");
    if (tag.equals("link")) {
        if (relType.equals("alternate")){
            link = parser.getAttributeValue(null, "href");
            parser.nextTag();
        }
    }
    parser.require(XmlPullParser.END_TAG, ns, "link");
    return link;
}

// Processes summary tags in the feed.
private String readSummary(XmlPullParser parser) throws IOException, XmlPullParserException {
    parser.require(XmlPullParser.START_TAG, ns, "summary");
    String summary = readText(parser);
    parser.require(XmlPullParser.END_TAG, ns, "summary");
    return summary;
}

// For the tags title and summary, extracts their text values.
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
    String result = "";
    if (parser.next() == XmlPullParser.TEXT) {
        result = parser.getText();
        parser.nextTag();
    }
    return result;
}
  ...
}

这可以很容易地修改以满足您的需求:将标签名称更改为您的标签,并将示例类修改为您想要的任何内容。我不确定您是否可以从属性中获取实例的价格,但如果添加子标签,您可能会得到相同的结果。例子:

<book>
    <type>sci-fi</type>
    <cost>
        <currency>USD</currency>
        <price>25</price>
    </cost>
</book>

有了成本,您也可以直接申请 25。

或者您可以继续使用属性系统,但您需要添加更多代码。而且,当前的 XML 文件你从来没有关闭标签(<book type="sci-fi">),你不应该在书标签内重复书标签。不是因为不鼓励这样做,而是因为您最终遇到了一个困难的局面,试图找出解析器找到的书标签。


此外,要编写 XML 文件,有许多不同的方法。为了在本地保存它,您可以使用 Serializable 更轻松地完成它:

public class Something implements Serializable{
...
}

然后使用 Object[In/Out]putStream 读取或写入:

    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("o.ser")));

    //Save the object
    oos.writeObject(instance);
    // close the writing.
    oos.close();

并加载:

ObjectInputStream ois= new ObjectInputStream(new FileInputStream(new File("o.ser")));

instance = (Something) ois.readObject();//or Something instance = (Something)...
ois.close;

但如果你真的想保存到 .xml 文件,这里有一种方法:

(这里使用的是内部存储,所以在应用程序的时候会删除。外部写入(公共访问区域)的概念是相同的,但写入方式不同)

public static String getString(String basetag, List<String> tags/*Raw name, e.g. book*/, List<String> value){
    if(basetag == null || basetag.equals("") || basetag.equals(" ")){
        throw new IllegalArgumentException("There has to be a base tag.");
    }
    String retval = "<" + basetag + ">\n";
    if(tags == null || value == null){
        throw new IllegalArgumentException("There have to be tags and values!");
    }
    if(tags.size() != value.size()){
        throw new IllegalArgumentException("There has to be as many tags as there are values");
    }
    assert tags.size() != 0;
    assert value.size() != 0;

    for(int i = 0; i < tags.size(); i++){
        String s = "<%s>%s</%s>\n";
        retval += String.format(Locale.ENGLISH, s, tags.get(i), value.get(i), tags.get(i));
    }
    return retval;
}

public static void save(String filename, String data, Context c){

    if(data != null && filename != null) {
        try {
            //Create the file if not exists
            File file = new File(c.getFilesDir() + "/", filename);
            if (file.getParentFile().mkdirs())
                file.createNewFile();
            //Access file and write
            FileOutputStream fos = c.openFileOutput(filename, Context.MODE_PRIVATE);
            fos.write(data.getBytes());

            fos.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }else{
        throw new NullPointerException("Filename and/or data is null");
    }
}

private static List load(String fn, Context c){
    String collected = null;
    FileInputStream fis = null;
    try{

        fis = c.openFileInput(fn);
        return parse(fis);

    }catch(Exception e){
        e.printStackTrace();
        return null;
    }finally{
        try {
            fis.close();
        } catch(NullPointerException npe){
            return null;
        } catch (Exception e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
        }
    }
}

public static List parse(InputStream in) throws XmlPullParserException, IOException {
    try {
        XmlPullParser parser = Xml.newPullParser();
        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
        parser.setInput(in, null);
        parser.nextTag();
        return readFeed(parser);
    } finally {
        in.close();
    }
}

在这篇文章的结尾,我真的建议你阅读关于这个主题的 android 文档,因为它包含很多有价值的信息,这些信息可能比这个答案更新(如果答案已经更新了很长时间)

于 2017-05-05T15:05:31.193 回答