arrayListOutOfBoundsException - PullRequest
       2

arrayListOutOfBoundsException

2 голосов
/ 13 июня 2010

Это мой класс отладчика. Может кто-нибудь попробовать и запустить его и посмотреть, когда не так? Я провел часы на этом уже. (

public class Debugger {

private String codeToDebug = "";

public Debugger(String code) {
    codeToDebug = code;
}

/**
 * This method itterates over a css file and adds all the properties to an arraylist
 */
public void searchDuplicates() {
    boolean isInside = false;
    ArrayList<String> methodStorage = new ArrayList();
    int stored = 0;
    String[] codeArray = codeToDebug.split("");

    try {
        int i = 0;
        while(i<codeArray.length) {
            if(codeArray[i].equals("}")) {
                isInside = false;
            }
            if(isInside && !codeArray[i].equals(" ")) {
                boolean methodFound = false;
                String method = "";
                int c = i;
                while(!methodFound) {
                    method += codeArray[c];
                    if(codeArray[c+1].equals(":")) {
                        methodFound = true;
                    } else {
                        c++;
                    }
                }
                methodStorage.add(stored, method);

                System.out.println(methodStorage.get(stored));
                stored++;

                boolean stillInside = true;
                int skip = i;
                while(stillInside) {
                    if(codeArray[skip].equals(";")) {
                        stillInside = false;
                    } else {
                        skip++;
                    }
                }
                i = skip;
            }
            if(codeArray[i].equals("{")) {
                isInside = true;
            }
            i++;
        }
    } catch(ArrayIndexOutOfBoundsException ar) {
        System.out.println("------- array out of bounds exception -------");
    }
}

/**
 * Takes in String and outputs the number of characters it contains
 * @param input
 * @return Number of characters
 */
public static int countString(String input) {
    String[] words = input.split("");
    int counter = -1;
    for(int i = 0; i<words.length; i++){
        counter++;
    }
    return counter;
}

public static void main(String[] args) {
    Debugger h = new Debugger("body {margin:;\n}");
    h.searchDuplicates();
}

}

Ответы [ 4 ]

1 голос
/ 13 июня 2010

Любое место, где элемент массива получается без проверки границ после манипулирования индексом, является кандидатом на ArrayIndexOutOfBoundsException.

. В приведенном выше коде есть как минимум два случая, когдас индексом манипулируют, не подвергаясь проверке границ.

  1. Цикл while проверяет условие !methodFound
  2. Цикл while проверяет условие stillInside

В этих двух случаях индексом манипулируют путем увеличения или добавления значения к индексу, но нет никаких связанных проверок до получения элемента из String[], поэтому существуетнет никакой гарантии, что указанный индекс находится за пределами массива.

0 голосов
/ 13 июня 2010

Я не удержался, чтобы реализовать эту задачу написания парсера CSS совершенно другим способом. Я разбил задачу разбора на множество маленьких.

  • Наименьшее называется skipWhitespace, так как оно понадобится везде при разборе текстовых файлов.
  • Следующим является parseProperty, который читает одно свойство вида name:value;.
  • Исходя из этого, parseSelector читает полный селектор CSS, начиная с имени селектора, открывающей скобки, возможно многих свойств и заканчивая закрывающей скобкой.
  • Все еще основываясь на этом, parseFile читает полный файл, состоящий, возможно, из множества селекторов.

Обратите внимание, насколько тщательно я проверил, достаточно ли index. Я делал это перед каждым доступом к массиву chars.

Я использовал LinkedHashMap s для сохранения свойств и селекторов, потому что карты такого типа запоминают, в каком порядке были вставлены объекты. Обычные HashMap s не делают этого.

Задача синтаксического анализа текстового файла, как правило, довольно сложна, и эта программа только пытается обработать основы CSS. Если вам нужен полный CSS-парсер, вам обязательно стоит поискать готовый. Этот не может обрабатывать @media или подобные вещи, где у вас есть вложенные блоки. Но не должно быть слишком сложно добавить его в существующий код.

Этот парсер не будет хорошо обрабатывать комментарии CSS. Это только ожидает их в нескольких местах. Если комментарии появляются в других местах, парсер не будет рассматривать их как комментарии.

import java.util.LinkedHashMap;
import java.util.Map;

public class CssParser {

  private final char[] chars;
  private int index;

  public Debugger(String code) {
    this.chars = code.toCharArray();
    this.index = 0;
  }

  private void skipWhitespace() {
    /*
     * Here you should also skip comments in the CSS file, which either look
     * like this comment or start with a // and go until the end of line.
     */
    while (index < chars.length && Character.isWhitespace(chars[index]))
      index++;
  }

  private void parseProperty(String selector, Map<String, String> properties) {
    skipWhitespace();

    // get the CSS property name
    StringBuilder sb = new StringBuilder();
    while (index < chars.length && chars[index] != ':')
      sb.append(chars[index++]);
    String propertyName = sb.toString().trim();

    if (index == chars.length)
      throw new IllegalArgumentException("Expected a colon at index " + index + ".");

    // skip the colon
    index++;

    // get the CSS property value
    sb.setLength(0);
    while (index < chars.length && chars[index] != ';' && chars[index] != '}')
      sb.append(chars[index++]);
    String propertyValue = sb.toString().trim();

    /*
     * Here is the check for duplicate property definitions. The method
     * Map.put(Object, Object) always returns the value that had been stored
     * under the given name before.
     */
    String previousValue = properties.put(propertyName, propertyValue);
    if (previousValue != null)
      throw new IllegalArgumentException("Duplicate property \"" + propertyName + "\" in selector \"" + selector + "\".");

    if (index < chars.length && chars[index] == ';')
      index++;
    skipWhitespace();
  }

  private void parseSelector(Map<String, Map<String, String>> selectors) {
    skipWhitespace();

    // get the CSS selector
    StringBuilder sb = new StringBuilder();
    while (index < chars.length && chars[index] != '{')
      sb.append(chars[index++]);
    String selector = sb.toString().trim();

    if (index == chars.length)
      throw new IllegalArgumentException("CSS Selector name \"" + selector + "\" without content.");

    // skip the opening brace
    index++;
    skipWhitespace();

    Map<String, String> properties = new LinkedHashMap<String, String>();
    selectors.put(selector, properties);

    while (index < chars.length && chars[index] != '}') {
      parseProperty(selector, properties);
      skipWhitespace();
    }

    // skip the closing brace
    index++;
  }

  private Map<String, Map<String, String>> parseFile() {
    Map<String, Map<String, String>> selectors = new LinkedHashMap<String, Map<String, String>>();
    while (index < chars.length) {
      parseSelector(selectors);
      skipWhitespace();
    }
    return selectors;
  }

  public static void main(String[] args) {
    CssParser parser = new CssParser("body {margin:prueba;A:B;a:Arial, Courier New, \"monospace\";\n}");
    Map<String, Map<String, String>> selectors = parser.parseFile();

    System.out.println("There are " + selectors.size() + " selectors.");
    for (Map.Entry<String, Map<String, String>> entry : selectors.entrySet()) {
      String selector = entry.getKey();
      Map<String, String> properties = entry.getValue();

      System.out.println("Selector " + selector + ":");

      for (Map.Entry<String, String> property : properties.entrySet()) {
        String name = property.getKey();
        String value = property.getValue();
        System.out.println("  Property name \"" + name + "\" value \"" + value + "\"");
      }
    }
  }
}
0 голосов
/ 13 июня 2010

Попробуйте оценить, существует ли ваш индекс в массиве ...

добавление:

while (!methodFound && c < codeArray.length) {

while (stillInside && skip < codeArray.length) {

if (i < codeArray.length && codeArray[i].equals("{")) {

Итак, ваш код выглядит так:

public class Debugger {

    private String codeToDebug = "";

    public Debugger(String code) {
        codeToDebug = code;
    }

    /**
     * This method itterates over a css file and adds all the properties to an
     * arraylist
     */
    public void searchDuplicates() {
        boolean isInside = false;
        List<String> methodStorage = new ArrayList<String>();
        int stored = 0;
        String[] codeArray = codeToDebug.split("");

        try {
            int i = 0;
            while (i < codeArray.length) {
                if (codeArray[i].equals("}")) {
                    isInside = false;
                }
                if (isInside && !codeArray[i].equals(" ")) {
                    boolean methodFound = false;
                    String method = "";
                    int c = i;
                    while (!methodFound && c < codeArray.length) {
                        method += codeArray[c];
                        if (codeArray[c].equals(":")) {
                            methodFound = true;
                        } else {
                            c++;
                        }
                    }
                    methodStorage.add(stored, method);

                    System.out.println(methodStorage.get(stored));
                    stored++;

                    boolean stillInside = true;
                    int skip = i;
                    while (stillInside && skip < codeArray.length) {
                        if (codeArray[skip].equals(";")) {
                            stillInside = false;
                        } else {
                            skip++;
                        }
                    }
                    i = skip;
                }
                if (i < codeArray.length && codeArray[i].equals("{")) {
                    isInside = true;
                }
                i++;
            }
        } catch (ArrayIndexOutOfBoundsException ar) {
            System.out.println("------- array out of bounds exception -------");
            ar.printStackTrace();
        }
    }

    /**
     * Takes in String and outputs the number of characters it contains
     * 
     * @param input
     * @return Number of characters
     */
    public static int countString(String input) {
        String[] words = input.split("");
        int counter = -1;
        for (int i = 0; i < words.length; i++) {
            counter++;
        }
        return counter;
    }

    public static void main(String[] args) {
        Debugger h = new Debugger("body {margin:prueba;\n}");
        h.searchDuplicates();
    }
}

Кроме того, объявление типов реализации является плохой практикой, из-за этого в приведенном выше коде я изменяю ArrayList variable = new ArrayList() на List variable = new ArrayList()

0 голосов
/ 13 июня 2010

Я думаю, что этот блок кодов может создать вашу проблему

int c = i;
while(!methodFound) {
    method += codeArray[c];
    if(codeArray[c+1].equals(":")) {
         methodFound = true;
    } else {
         c++;
    }
}


int skip = i;
while(stillInside) {
    if(codeArray[skip].equals(";")) {
       stillInside = false;
    } else {
       skip++;
    }
 }
 i = skip;

Причина в том, что если условие истинно, а i = codeArray.length - 1. C + 1 создаст ошибку ArrayIndexOutOfBound

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...