2009-05-05 2 views
1

У меня есть большая строка, подобная этой:Поиск большой строку, чтобы увидеть, если недействителен "параметр" существует

BREW горшок HTCPCP/1.0

Accept-дополнения: #milk; 3 # виски; выплеска

Content-Length: 5

Content-Type: сообщение об/кофейник

У меня также есть массив с несколькими дополнениями (#whiskey, #espresso и т. Д.). Мне нужно отправить сообщение об ошибке, если эта большая строка содержит дополнение, которое НЕ находится в массиве доступных дополнений. Например, если часть «Accept-Additionaldition» в строке содержала «#bricks; 3», была произведена ошибка, так как она не находится в массиве.

Как бы это сделать на Java? У меня возникли проблемы с реализацией этой части, хотя я закодировал остальную часть программы (что многие из вас могут распознать). Как бы я закодировал следующую проблему с акцентом на том, что добавление не доступно?

ответ

1

Этот код делает несколько предположений о вводе. Похоже, вы можете разделить каждый токен еще на #; компоненты. Использование списка для параметра приемлемых жидкостей будут очистим код немного (просто использовать liquids.contains (String s))

static String[] liquids = {"#milk;3", "#whiskey;splash"}; 

    public static void parseString(String input) 
    { 
    // Break the String down into line-by-line. 
    String[] lines = input.split("" + '\n'); 
    for (int line_index = 0; line_index < lines.length; line_index++) 
    { 
     if (lines[line_index].length() > 16) 
     { 
     // Assume you're delimiting by '#' 
     String[] tokens = lines[line_index].split("#"); 
     if (tokens.length > 1) 
     { 
      // Start at index = 1 to kill "Accept-Additions:" 
      for (int token_index = 1; token_index < tokens.length; token_index++) 
      { 
      boolean valid = false; 
      for (int liquids_index = 0; liquids_index < liquids.length; liquids_index++) 
      { 
       if (liquids[liquids_index].equals("#" + tokens[token_index])) 
       { 
       valid = true; 
       // break to save some time if liquids is very long 
       break; 
       } 
      } 
      if (!valid) 
      { 
       throwError("#" + tokens[token_index]); 
      } 
      } 
     } 
     } 
    } 
    } 

    public static void throwError(String error) 
    { 
    System.out.println(error + " is not in the Array!"); 
    } 
+0

Это очень близко к тому, что я хочу, хотя массив не содержит суммы, поэтому значения в массиве соответствуют строкам «# цельное молоко». –

+0

Я предполагаю, что OP хотел быть ложкой ...Вместо этого беспорядка вложенных циклов я начинал с обертывания String в StringReader, а в LineNumberReader - с помощью цикла readLine(). String.startsWith() - это чистый способ определения линий, о которых вы заботитесь (хотя сначала нужно обрезать()), и нет веских оснований для проверки длины линии. Рефакторируйте токенизацию в свой собственный метод для потенциального повторного использования, и, как я заметил ниже, исследуйте HashSet, чтобы найти допустимые/недопустимые значения. – kdgregory

1

Вы проанализировали бы строку. Глядя на это, вы получаете один набор опций в строке, поэтому вы можете искать все строки, начинающиеся с ACCEPT-ADDITIONS. Затем вам нужно извлечь дополнения, которые кажутся отдельными с полуколониями, с указанием String.split(). Затем перейдите по массиву resuling, чтобы найти дополнения.

Или вы можете создать грамматику и использовать такой инструмент, как ANTLR, для генерации вашего синтаксического анализатора.

+0

И быстрый способ проверить это, чтобы использовать класс Массивов, чтобы проверить (а не перебор): как Arrays.binarySearch (additionsArray, parsedString), который будет возвращать <0, если добавление не в массиве. – mattandrews

+0

Не знаете, как вам поможет двоичный поиск. Вы в основном ищете членов одного набора, которые не отображаются в другом. Поэтому я бы создал HashSet с действительными дополнениями и перебирал значения, указанные в файле. – kdgregory

0

Вот возможное решение с использованием регулярных выражений. Он извлекает строку «Принять-Дополнения» из полезной нагрузки, а затем проверяет каждую пару «ключ-значение» формы #foo;bar.

final String[] VALID_ADDITIONS = { 
    "milk", "whiskey" 
}; 

final Pattern LINE = Pattern.compile("Accept-Additions:(.+)$", Pattern.MULTILINE); 
final Pattern ADDITIONS = Pattern.compile("#(.+?);([^#]+)"); 

void checkValidAdditions(String request) { 
    Matcher lineMatcher = LINE.matcher(request); 
    if (!lineMatcher.find()) { 
     // no additions - do whatever is appropriate here 
     throw new IllegalArgumentException("Additions line not found"); 
    } 
    String line = lineMatcher.group(1); 
    Matcher additions = ADDITIONS.matcher(line); 
    while (additions.find()) { 
     String key = additions.group(1); 
     //String value = additions.group(2); 

     boolean validKey = false; 
     for (String validAddition : VALID_ADDITIONS) { 
      if (key.equals(validAddition)) { 
       validKey = true; 
      } 
     } 
     if (!validKey) { 
      // ... 
     } 
    } 
} 

Первое регулярное выражение извлекает соответствующую строку из запроса. Второй - извлекает пары ключ-значение. Упомяните о следующих мерах:

  • Этот метод не будет правильно обрабатывать неверные запросы - только недействительные «ключи».

  • Если вы допускаете разную капитализацию (например, «ПРИНЯТЬ-ДОБАВКИ», «принимать дополнения»), добавьте флаг Pattern.CASE_INSENSITIVE, то есть Pattern.MULTILINE & Pattern.CASE_INSENSITIVE.

+0

Я пробовал ваш код, но я получаю исключение IllegalStateException, когда пытаюсь отправить строку с клиента. –

+0

Какое сообщение об исключении? – harto

+0

Я предполагаю, что первое регулярное выражение не совпало. Я немного расслабился - и добавил список «оговорок» ... – harto

Смежные вопросы