better/quicker 方式? java 使用 stax 的文字冒险

better/quicker way? java text adventure with stax

我编写了一小段代码。我可能是错的,但我相信我是在所谓的 staX 中做到的(说实话,我不确定,我只是从我身边的一本随机书中学到的)。它运行良好(或者至少它是,但我将数组列表更改为数组,而且我也没有彻底测试 gainitem 和 neededitem 部分,但它们似乎在工作)但这些也不是我的主要关注点。我想知道是否有更好的方法(使用 staX)来重构我的代码。我也在一边尝试制作一个程序,该程序使用 classes 通过代码创建对象,所以我只需要 运行 通过它几次,然后所有内容都被存储起来,我可以使用那些,但为了清楚起见,我不希望这个答案。我还注意到其他事情。当我 运行 程序时,它的启动大小约为 11MB。它缓慢但肯定会获得收益。所以我不断地 运行 输入以查看会发生什么,它会上升到大约 500-550MB 并保持在这个范围内。这是否意味着我忘记正确关闭某些东西,或者只是预料之中,就像 GC 只是很慢?听起来绝对不是这样,我觉得更像是我在某个地方的错。

我有一个主要的 class 测试 userInput,并保持 运行ning 直到终止号码,但这是我所知道的唯一可能重要或有用的东西.

currentGame.selectedOptionSetUp(userInputIntValue);
currentGame.getOptions();
currentGame.printOptions();

对于我的代码的主要部分。我的很多 if/else 确实做出了预期结果的假设,我有点 运行ning 而在我的 if 中直到 returns 为真,我知道这一点,我写道在我的一个 else 语句旁边的评论。

此外,在我的代码的某些部分中,我相信在某些嵌套语句中可能存在挥之不去的关闭方法,我相信如果它们被多次调用,则不会发生任何事情,所以我只是在尝试时将它们留在身边弄清楚是什么让程序能够占用这么多内存,我是否正确,可以多次调用 close 方法?

代码:

 public class TheGame {

private int testAreaID;
private int areaID = -1;
private int sectorID= -1;
private String areaDescription = "";
private String sectorDescription = "";
private String[] possibleOptions = new String[10];
private String[] newAreaOptions = new String[5];
private String[] descriptorOptions = new String[5];
private String[] userGainedItems = new String[10];
private String neededItem = null;
private boolean optionRequiredItem= false;
private boolean descriptorReqItem = false;
private boolean areaReqItem = false;
private String gainedItemText = null;

private String gameFileName="";
private XMLInputFactory inputFactory = XMLInputFactory.newFactory();

public TheGame(String gameFile)
{
    gameFileName = gameFile;
    getIntro();
    printIntro();
    getOptions();
    printOptions();
}

private void getIntro(){
    try{
        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);

        if(findIntro(gameFileXML)){         
            while(findEventLoc(gameFileXML,XMLStreamConstants.END_ELEMENT,"Intro")== false){
                if (gameFileXML.getEventType() == XMLStreamConstants.START_ELEMENT && !(gameFileXML.getLocalName().equals("Intro"))){
                    String testString = gameFileXML.getLocalName();

                    switch (testString){
                        case "AreaID" : areaID = Integer.parseInt(gameFileXML.getElementText());
                                        break;
                        case "StartDescription" : areaDescription = gameFileXML.getElementText();
                                                  break;
                        case "StartSector" : sectorID = Integer.parseInt(gameFileXML.getElementText());
                    }
                }
                else gameFileXML.next();
            }

        }
            else gameFileXML.next();

        gameFile.close();
        gameFileXML.close();
        gameFile = null;
        gameFileXML = null;
    }   
    catch (IOException | XMLStreamException e){
        System.out.println(e);
    }
} // end of getIntro() method

private void printIntro()
{
    System.out.println(areaDescription + "\n");
    getSectorDescription();
    printSectorDescription();
}

private void getSectorDescription()

{
    try
    {
        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);
        completeBreak:
        while(gameFileXML.hasNext()){
            if (findCorrectSector(gameFileXML)){
                while(gameFileXML.hasNext()){
                    if(findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,"Description")){
                        sectorDescription = gameFileXML.getElementText();
                        break completeBreak;
                    }
                    else gameFileXML.next();
                }
            }
            else gameFileXML.next();
        }

        gameFile.close();
        gameFileXML.close();
        gameFile = null;
        gameFileXML = null;
    }

    catch (IOException | XMLStreamException e)
    {
        System.out.println(e);
    }
}

private void printSectorDescription()
{
    System.out.println(sectorDescription + "\n");
} // end of printSectorDescription() method

public void getOptions()
{
    try
    {
        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);

        if(findCorrectSector(gameFileXML)){
            while(gameFileXML.hasNext()){
                if(findEventLoc(gameFileXML,XMLStreamConstants.END_ELEMENT,"Sector")){
                    gameFileXML.close();
                    gameFile.close();
                    break;
                }           
                else if (findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,"Exit")){
                    if((neededItem = returnAttData(gameFileXML,"ReqItem"))!= null){
                        optionRequiredItem=true;

                    }

                    addToArray(possibleOptions,gameFileXML.getElementText());

                    gameFileXML.next();
                }
                else if (findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,"Leave")){
                    if((neededItem = returnAttData(gameFileXML,"ReqItem")) != null){
                        areaReqItem=true;
                    }
                    String areaOption = gameFileXML.getElementText();
                    addToArray(possibleOptions,areaOption);
                    addToArray(newAreaOptions,areaOption);
                    gameFileXML.next(); 
                }
                else if (findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,"Option")){
                    if((neededItem = returnAttData(gameFileXML,"ReqItem")) != null){
                        descriptorReqItem = true;
                    }
                    String descriptorOption = gameFileXML.getElementText();
                    addToArray(possibleOptions,descriptorOption);
                    addToArray(descriptorOptions,descriptorOption);
                    gameFileXML.next();
                }
                else gameFileXML.next();            
            }
        }               
        gameFile.close();
        gameFileXML.close();
        gameFile = null;
        gameFileXML = null;

    }
    catch (IOException | XMLStreamException e)
    {
        System.out.println(e);
    }
} 

public void printOptions()

{
    for (int i = 0; i< possibleOptions.length -1;i++)
    {
        if (possibleOptions[i] != null)
        System.out.println(i + " " + possibleOptions[i]);
    }
} // end of printOptions() method

public String[] returnOptions()
{
    return possibleOptions;
}

public void selectedOptionSetUp(int userOptionSelected)
{
    System.out.println("");
    String textOfOption = possibleOptions[userOptionSelected];

    if (isItemInArray(newAreaOptions,textOfOption))
    {
        checkGainItem("Leave",textOfOption);



        if(areaReqItem){
            if (userHasItem(neededItem)){
                sectorID = 0;
                setAreaID(textOfOption);
                setAreaDescription();
                printArea();
            }
            else System.out.println("You do not have an item needed to continue\n");
        }
        else{
            sectorID = 0;
            setAreaID(textOfOption);
            setAreaDescription();
            printArea();
        }
        if(gainedItemText != null){
            System.out.println(gainedItemText);
        }

    }
    else if(isItemInArray(descriptorOptions,textOfOption))
    {
        checkGainItem("Option",textOfOption);

        if(descriptorReqItem){
            if(userHasItem(neededItem)){
                printDescriptorOption(textOfOption);
            }
            else System.out.println("You do not have an item needed to continue\t");
        }
        else printDescriptorOption(textOfOption);

        if(gainedItemText != null){
            System.out.println(gainedItemText);
        }
    }
    else
    {
        checkGainItem("Exit",textOfOption);



        if(optionRequiredItem){
            if(userHasItem(neededItem)){
                setSector(textOfOption);
            }
            else System.out.println("You do not have an item needed to continue\t");
        }
        else setSector(textOfOption);
        if(gainedItemText != null){
            System.out.println(gainedItemText);
        }
    }
    gainedItemText = null;
    optionRequiredItem = false;
    areaReqItem = false;
    descriptorReqItem = false;
    neededItem= null;
    getSectorDescription();
    printSectorDescription();
    Arrays.fill(possibleOptions, null);;
    Arrays.fill(newAreaOptions,null);
    Arrays.fill(descriptorOptions, null);
} 

private void setSector(String optionText)
{
    try
    {
        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);

        allLoops:

        if (findCorrectArea(gameFileXML) ){
            while (findEventLoc(gameFileXML,XMLStreamConstants.END_ELEMENT,"Sectors") == false){
                if(findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,"Sector")){ 
                    while(gameFileXML.hasNext()){
                        if(findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,"Exit")){
                            int tempSectorID = Integer.parseInt(returnAttData(gameFileXML,"ID"));
                            if(gameFileXML.getElementText().equals(optionText)){
                                sectorID= tempSectorID;
                                gameFileXML.close();
                                gameFile.close();
                                break allLoops;  
                            }
                            else gameFileXML.next();     
                        }
                        else gameFileXML.next();
                    }
                }       
                else gameFileXML.next();
            } //end of first while
        }            
        else gameFileXML.next();

        gameFile.close();
        gameFileXML.close();
        gameFile = null;
        gameFileXML = null;
    }

    catch (IOException | XMLStreamException e)
    {
        System.out.println(e);
    }
}

private void setAreaID(String exitText)
{
    try
    {
        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);


             if(findCorrectSector(gameFileXML))
             {  
                 boolean foundNewAreaID = false;
                 while(foundNewAreaID == false){
                     if (findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,"Leave")){
                         int tempAreaID = Integer.parseInt(returnAttData(gameFileXML,"ID")); // FLAG possible bug issue
                         if (gameFileXML.getElementText().equals(exitText)){ 
                             areaID = tempAreaID;
                             foundNewAreaID = true; 
                         }
                         else gameFileXML.next();
                     }
                     else gameFileXML.next();
                 }
             }
             else gameFileXML.next(); //possibly dangerous to have this with a while inside if?

        gameFile.close();
        gameFileXML.close();
        gameFile = null;
        gameFileXML = null;
    }

    catch (IOException | XMLStreamException e)
    {
        System.out.println(e);
    }
} // end of setArea() method

private void setAreaDescription()
{
    try
    {
        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);

        allLoops:
        while(gameFileXML.hasNext())
        {
            if(gameFileXML.getEventType() == XMLStreamConstants.START_ELEMENT && gameFileXML.getLocalName().equals("Area"))
            {
                if(Integer.parseInt(returnAttData(gameFileXML,"ID")) == areaID)
                {
                    while ((gameFileXML.getEventType() == XMLStreamConstants.END_ELEMENT && gameFileXML.getLocalName().equals("Description"))== false)
                    {
                        if (gameFileXML.getEventType() == XMLStreamConstants.START_ELEMENT && gameFileXML.getLocalName().equals("Description"))
                        {
                            areaDescription = gameFileXML.getElementText();
                            break allLoops;
                        }
                        else gameFileXML.next();
                    }
                }
                else gameFileXML.next();
            }
            else gameFileXML.next();
        }
        gameFileXML.close();
        gameFile.close();
        gameFileXML = null;
        gameFile = null;
    }

    catch (IOException | XMLStreamException e)
    {
        System.out.println(e);
    }
}

private void printDescriptorOption(String userOption)
{
    try
    {
        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);
        allLoops:
        while(gameFileXML.hasNext())
        {
            if(gameFileXML.getEventType() == XMLStreamConstants.START_ELEMENT && 
                    gameFileXML.getLocalName().equals("Area") && 
                    Integer.parseInt(returnAttData(gameFileXML,"ID")) == areaID)
            {
                while((gameFileXML.getEventType() == XMLStreamConstants.END_ELEMENT && gameFileXML.getLocalName().equals("Area"))== false)
                {
                    if(gameFileXML.getEventType() == XMLStreamConstants.START_ELEMENT &&
                            gameFileXML.getLocalName().equals("Sector") &&
                            Integer.parseInt(returnAttData(gameFileXML,"ID")) == sectorID)
                    {
                        while((gameFileXML.getEventType() == XMLStreamConstants.END_ELEMENT &&
                                gameFileXML.getLocalName().equals("Sector")) == false)
                        {
                            if(gameFileXML.getEventType() == XMLStreamConstants.START_ELEMENT &&
                                    gameFileXML.getLocalName().equals("Option"))
                            {
                                String tempOptionString = gameFileXML.getAttributeValue(0);
                                if(gameFileXML.getElementText().equals(userOption))
                                {
                                    System.out.println(tempOptionString + "\n");
                                    gameFileXML.close();
                                    gameFile.close();
                                    break allLoops;
                                }
                                else gameFileXML.next();
                            }
                            else gameFileXML.next();
                        }
                    }
                    else gameFileXML.next();    
                }
            }
            else gameFileXML.next();
        }
        gameFile.close();
        gameFileXML.close();
        gameFile = null;
        gameFileXML = null;
    }
    catch (IOException | XMLStreamException e){
        System.out.println(e);
    }
}

private void printArea(){
        if(testAreaID != areaID){
            System.out.println(areaDescription);
        }   
    } // end of printArea() method

private void checkGainItem(String optionType, String optionText){
    String gainedItem = null;
    try{

        FileReader gameFile = new FileReader(gameFileName); 
        XMLStreamReader gameFileXML = inputFactory.createXMLStreamReader(gameFile);

        if (findCorrectSector(gameFileXML)){
            while(gameFileXML.hasNext()){
                if(findEventLoc(gameFileXML,XMLStreamConstants.START_ELEMENT,optionType)){
                    String potentialItem = returnAttData(gameFileXML,"GainItem");
                    String potentialItemResponse = returnAttData(gameFileXML,"GainItemText");
                    if(gameFileXML.getElementText().equals(optionText)){
                        gainedItem = potentialItem;
                        gainedItemText = potentialItemResponse;
                        break;
                    }       
                }
                else gameFileXML.next();
            }
        }
        else gameFileXML.next();
        gameFile.close();
        gameFileXML.close();    

        if(gainedItem != null){
            if(isItemInArray(userGainedItems,gainedItem)){
                gainedItemText="an item was here";
            }
            else {
                addToArray(userGainedItems,gainedItem);
            }
        }
        gameFileXML.close();
        gameFile.close();
        gameFileXML = null;
        gameFile = null;
    }
    catch (IOException | XMLStreamException e){
        System.out.println(e);
    }
}

private String returnAttData(XMLStreamReader reader, String att){
    int count = reader.getAttributeCount();
    String attVal = null;
    for(int i = 0; i < count; i++){
        if(reader.getAttributeLocalName(i).equals(att)){
            attVal = reader.getAttributeValue(i);//this should ALWAYS happen, or code might break
            break;
        }
    }
    return attVal;
}

private boolean findEventLoc(XMLStreamReader reader, int ele, String eleName){
    boolean foundEvent = false;

    if(reader.getEventType() == ele && reader.getLocalName().equals(eleName)){
         foundEvent= true;;
    }
    else foundEvent = false;
    return foundEvent;
}

private boolean findIntro(XMLStreamReader reader) throws XMLStreamException{
    boolean foundIntro = false;

    while(foundIntro == false){
        if(findEventLoc(reader,XMLStreamConstants.START_ELEMENT,"Intro")){
            foundIntro = true;
        }
        else reader.next();
    }
    return foundIntro;
}
private boolean findCorrectArea(XMLStreamReader reader) throws XMLStreamException{
    boolean foundCorrectArea = false;
    //assumes foundCorrectArea will always become true
    while(foundCorrectArea == false) {
    if(findEventLoc(reader,XMLStreamConstants.START_ELEMENT,"Area")){
        if (Integer.parseInt(returnAttData(reader,"ID")) == areaID ) {
            foundCorrectArea = true;
        }
        else reader.next();
    }
    else reader.next();
    }
    return foundCorrectArea;
}

private boolean findCorrectSector(XMLStreamReader reader) throws XMLStreamException{
    boolean foundCorrectSector = false;

    while (foundCorrectSector == false){
        if(findCorrectArea(reader)){
            while(foundCorrectSector == false) {
                if(findEventLoc(reader,XMLStreamConstants.START_ELEMENT,"Sector")){
                    if(Integer.parseInt(returnAttData(reader,"ID"))== sectorID){
                        foundCorrectSector = true;
                    }
                    else reader.next();
                }
                else reader.next();
            }
        }
        else reader.next();
    }
    return foundCorrectSector;
}

private boolean userHasItem(String item){
    boolean hasItem = false;
    if (isItemInArray(userGainedItems,item)){
        hasItem = true;
    }
    else hasItem = false;
    return hasItem;
}

private void addToArray(String[] array, String item){
    for(int i = 0; i < array.length - 1;i++){
        if (array[i] == null){
            array[i]= item;
            break;
        }
    }
}

private boolean isItemInArray(String[] array, String item){
    boolean itemFound = false;
    for(int i=0; i < array.length -1;i++){
        if(array[i] == null) break;
        if (array[i].equals(item)){
            itemFound = true;
            break;
        }
    }
    return itemFound;
}
}

作为我想知道的内容的回顾:有什么更好的方法来做同样的事情,而无需在 staX 中使用任何额外的自制 classes(如果那是我正在使用的,尽管只是冰山一角)。也许某处有泄漏?对 FileReader 和 XMLStreamReader 使用空值合适吗?

感谢您的宝贵时间。

如果 XML 文件不是很大,我建议使用 DOM 解析器并应用 XPath 表达式。与像 STaX 这样的流 XML 代码相比,此代码更易于编写和维护。我自己确实使用 STaX 处理大型文档。

对于 XPath,我通常使用 http://jaxen.org/faq.html,而不是 javax.xml.xpath 代码库。

如果您的代码中存在内存使用问题,您应该尝试使用像 https://visualvm.github.io/ 这样的分析工具或像 JProfiler 这样的分析器。

我建议使用 InputStreams 而不是 FileReaders。 FileReader class 对 XML 文件的字符编码进行了假设。