Java String索引超出范围:-4

时间:2014-04-27 06:31:20

标签: java parsing substring indexof

我有一个字符串

statdata = "Health 433 (+78) Attack damage 52.3 (+3.9) Health regen. 6.95 (+0.5) Attack speed 0.64 (+3.7%) Mana 230 (+70) Armor 18 (+3.2) Mana regen. 6.9 (+0.6) Magic res. 30 (+0) Range 150 (Melee) Mov. speed 350";

我正在使用子字符串和indexOf从字符串中提取数据并将其解析为双精度数。这是我的班级:

package Engine;

import WebScraper.getWikiStats;

public class MathParse {
    public static double returnStat;
    public static int indexh;
    public static String statdata;
    public static getWikiStats getStats = new getWikiStats();
    public double stringToDouble(String s){
        s.replaceAll("[^\\d.]", ""); //Remove all characters that aren't a number or a decimal
        double d = Integer.parseInt(s);
        return d;
    }

    public double parseStatData(String stat, String champion){
        statdata = "Health 433 (+78) Attack damage 52.3 (+3.9) Health regen. 6.95 (+0.5) Attack speed 0.64 (+3.7%) Mana 230 (+70) Armor 18 (+3.2) Mana regen. 6.9 (+0.6) Magic res. 30 (+0) Range 150 (Melee) Mov. speed 350";
        System.out.println(statdata);
        if(stat.equalsIgnoreCase("health")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health") + 7, 3));
        }else if(stat.equalsIgnoreCase("healthpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health") + 10, 3));
        }else if(stat.equalsIgnoreCase("mana")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana") + 5, 3));
        }else if(stat.equalsIgnoreCase("manapl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana") + 8, 2));
        }else if(stat.equalsIgnoreCase("healthr")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health regen.") + 14, 4));
        }else if(stat.equalsIgnoreCase("healthrpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health regen.") + 18, 10));
        }else if(stat.equalsIgnoreCase("manar")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana regen.") + 12, 4));
        }else if(stat.equalsIgnoreCase("manarpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana regen.") + 16, 10));
        }else if(stat.equalsIgnoreCase("range")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Range") + 6, 3));
        }else if(stat.equalsIgnoreCase("ad")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack damage") + 14, 5));
        }else if(stat.equalsIgnoreCase("adpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack damage") + 19, 8));
        }else if(stat.equalsIgnoreCase("as")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack speed") + 13, 5));
        }else if(stat.equalsIgnoreCase("aspl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack speed") + 19, 4));
        }else if(stat.equalsIgnoreCase("armor")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Armor") + 6, 4));
        }else if(stat.equalsIgnoreCase("armorpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Armor") + 11, 5));
        }else if(stat.equalsIgnoreCase("mr")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Magic res.") + 11, 4));
        }else if(stat.equalsIgnoreCase("mrpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Magic res.") + 16, 5));
        }else if(stat.equalsIgnoreCase("ms")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mov. Speed") + 11, 3));
        }else{
            returnStat = 0;
        }
        return returnStat;
    }
}

以下是我使用parseStatData方法时遇到的错误:

"main" java.lang.StringIndexOutOfBoundsException: String index out of range: -4
at java.lang.String.substring(Unknown Source)
at Engine.MathParse.parseStatData(MathParse.java:18)
at Champions.champTemplate.showStats(champTemplate.java:27)
at Main.TheoryCrafting.theoryLoop(TheoryCrafting.java:29)
at Main.MainClass.checkCommand(MainClass.java:32)
at Main.MainClass.start(MainClass.java:22)
at Main.MainClass.main(MainClass.java:10)

我不知道出了什么问题,我真的很感激帮助。

1 个答案:

答案 0 :(得分:1)

如果第一个参数大于第二个参数,

String#substring()意味着抛出IndexOutOfBoundsException

实际上,子字符串打算采用最低的起始索引,并且一直向上但不包括您提供的最高索引值。它的范围为[a,b)。

如果是> b,那么你会选择一个非常奇怪的范围 - 而且Java选择在这种情况下出错。

罪魁祸首 [可能全部]是您的substring陈述:

statdata.substring(statdata.indexOf("Health") + 7, 3);

除非"Health"的索引为负数,否则您将始终超越此子字符串的范围。

或许您想要反转订单:

statdata.substring(3, statdata.indexOf("Health") + 7);

...虽然,这可能是解决更大问题的绷带解决方案 - 您试图用子串解析一个巨大的字符串,并且从长远来看这是不可维护的。 / p>

两个解决方案 - 一个天真,一个稍微好于天真 - 使用String[]Map<String, String>来保存您的数据。

这是使用Map的解决方案:

Map<String, String> statData = new HashMap<>();

statData.put("Health", "433 (+78)");
statData.put("Attack damage", "52.3 (+3.9)");
// and so forth