Java正确解析

时间:2017-08-02 19:59:21

标签: java parsing design-patterns

我找到了将手写数据解析为对象的最佳方法。

假设我有一个名为IEvent的界面。

假设我有两个类EventNewPlayerEventUpdateTime,它们都实现了接口IEvent

EventNewPlayer需要2个整数和一个字符串。让我们说位置XY以及播放器的名称

班级EventUpdateTime只需要一个参数:时间。

我想从手写文件中创建尽可能多的事件

该文件如下所示:

NEWPLAYER, 4, 2, joe
NEWPLAYER, 8, 9, bob
UPDATETIME, 1
NEWPLAYER, 8, 9, carl
UPDATETIME, 3

我想从此文件生成事件列表。 此外,我希望将来添加尽可能多的事件。

这样做的最佳/适当/可维护方式是什么?

对于任何英语错误感到抱歉,英语不是我的第一句话。

4 个答案:

答案 0 :(得分:2)

一种OOP式的方式:

1)创建一个名为StringEventFactory的基本接口和一个名为parseFromArray的非静态函数,将一个字符串数组作为参数并返回IEvent;还创建一个名为className的静态函数,它返回每个事件类的文件名。

2)为每个事件创建一个继承自...Factory的相应StringEventFactory类,并实现parseFromArray函数,从字符串数组数据中创建该类型的事件。

3)创建一个哈希表,其中包含:

  • 键是存储在文本文件中的类名,例如“NEWPLAYER”等。
  • 值是对应的类..Factory对象

4)对于每一行,将其拆分为一个字符串数组,并使用第一个元素从哈希表中获取StringEventFactory对象。将数组的其余部分传递给其parseFromArray函数以创建所需的事件对象

这样就可以很容易地添加新的类规范,而不使用丑陋的switch语句。

编辑:代码+规范略有变化

 interface StringEventFactory {
    public static string className();
    public IEvent parseFromArray(string[]);
 };

 class EventNewPlayerFactory implements StringEventFactory
 {
    public static string className() { return "NEWPLAYER"; }

    public IEvent parseFromArray(string[] info) 
    {
        if (info.length != 4) // includes the class name
            return null;

        // sanity check
        if (!info[0].equals(className()) || info[3].isEmpty()) 
            return null;

        int x, y;
        try {
            x = Integer.parseInt(info[1]);
            y = Integer.parseInt(info[2]);
        }
        catch (NumberFormatException ex) {
            // notify?
            return null;
        }

        return new EventNewPlayer(x, y, info[3]);
    }
 };

 // similarly for EventUpdateTime ...

 // main body
 public static void main(string[] args)
 {
    Hashtable<string, StringEventFactory> factories = new Hashtable<string, StringEventFactory>();

    factories.put(EventNewPlayerFactory.className(), new EventNewPlayerFactory());
    // similarly for other classes

    List<IEvent> eventList = new ArrayList();

    // file parsing
    FileReader input = new FileReader(fileName);
    BufferedReader read = new BufferedReader(input);
    String line = null;

    while ((line = read.readLine()) != null)
    {    
        String[] array = line.split(",");
        for (int i = 0; i < array.length; i++)
            array[i] = array[i].trim();

        // fetch the factory class
        StringEventFactory fact = factories.get(array[0]);
        if (fact == null) {
            // class name does not exist
            continue;
        }

        StringEvent out = fact.parseFromArray(array);
        if (out == null) {
            // parameters were incorrect!
            continue;
        }

        // success! add to list
        eventList.add(out);
    }
 }

很抱歉,如果它不能直接使用并且语法错误,我的Java稍微生锈了,但希望是你想要的。

答案 1 :(得分:0)

给定数据数组

String[] data = { "ObjA,0,0,Bob", "ObjB,0" };

Enum定义为

public enum MyEnum {

    ObjA, ObjB;
}

我会使用类似的东西:

for ( String line : data ) {

    Object obj;

    String[] parts = line.split(",");

    switch(MyEnum.valueOf(parts[0])) {

        case ObjA:
            obj = new ObjectOfTypeA(parts);
            break;

        case ObjB:
            obj = new ObjectOfTypeB(parts);
            break;
    }

然后每个对象都可以处理自己的参数:

public ObjectOfTypeA(String[] params) {

    x = params[1];
    y = params[2];
    name = params[3];
}

public ObjectOfTypeB(String[] params) {

    ticks = params[1];
}

对于您创建的每个新对象,您将需要将其添加到Enum列表,switch case,然后显然是创建类本身。

答案 2 :(得分:0)

我建议你使用有限状态机。它维护简单灵活。您将来可以添加不同的处理程序。

以下是我的XML解析示例 - https://github.com/kurkov/XMLParser 但是你可以为文本文件解析做类似的事情。

答案 3 :(得分:-1)

你按顺序:

  • 逐行阅读您的文件:Files.readAllLines(//path)可能很有用
  • split over&#34;,&#34;并检查第一个文本是否为NEW ...或UPD ...(检查lentgh以确定)
  • 创建object(并将其存储在List中,以便在文件讲座后检索

所有这些都将具有以下外观:

public static void main(String args[]) {
        List<EventNewPlayer> listPlayer = new ArrayList<>();
        List<EventUpdateTime> listTime = new ArrayList<>();

        for (String line : Files.readAllLines("myfile.txt")) {

            String[] array = line.split(",");

            if (array[0].equals("NEWPLAYER") && array.length == 4) {
                listPlayer.add(new EventNewPlayer(array[1], array[2], array[3]));

            } else if (array[0].equals("UPDATETIME") && array.length == 2) {
                listPlayer.add(new EventUpdateTime(array[1]));
            }
        }
    }

如果您的文件中存在错误,则array.length的checl只是一个安全措施,以避免IndexOutOfBoundsException