【问题标题】:Searching a large string to see if invalid "parameter" exists搜索大字符串以查看是否存在无效的“参数”
【发布时间】:2009-05-05 23:51:02
【问题描述】:

我有一个大字符串,类似于这个:

BREW 锅 HTCPCP/1.0

接受-添加:#milk;3#whiskey;splash

内容长度:5

内容类型:消息/咖啡壶

我还有一个包含几个添加项(#whiskey、#espresso 等)的数组。如果这个大字符串包含不在可用添加数组中的添加,我需要做的是发送错误。例如,如果字符串的“Accept-Additions”部分包含“#bricks;3”,则会产生错误,因为它不在数组中。

我将如何在 Java 中解决这个问题?尽管我已经编写了程序的其余部分(你们中的许多人可能都知道),但我在实现这部分时遇到了麻烦。我将如何对以下问题进行编码,重点是添加不可用?

【问题讨论】:

    标签: java string


    【解决方案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!");
      }
    

    【讨论】:

    • 这和我想要的很接近,虽然数组不包含数量,所以数组中的值是沿着“#whole-milk”的行。
    • 我猜 OP 想要被喂饱......而不是这种混乱的嵌套循环,我会先将字符串包装在 StringReader 中,然后在 LineNumberReader 中,然后使用 readLine( ) 环形。 String.startsWith() 是一种识别您关心的行的简洁方法(尽管您应该首先 trim() ),并且没有充分的理由检查行长。将标记化重构为自己的方法以实现潜在的可重用性,正如我在下面提到的,探测 HashSet 以查找有效/无效值。
    【解决方案2】:

    你会解析字符串。查看它,每行有一组选项,因此您可以查找以 ACCEPT-ADDITIONS 开头的所有行。然后你必须提取添加,它们似乎用分号分隔,表示 String.split()。然后遍历结果数组以查找添加项。

    或者您可以创建一个语法,并使用诸如 ANTLR 之类的工具来生成您的解析器。

    【讨论】:

    • 并且一个快速的测试方法是使用 Arrays 类来检查(而不是迭代):像 Arrays.binarySearch(additionsArray, parsedString) 如果添加不在你的数组。
    • 不确定二进制搜索如何帮助您。您基本上是在寻找一组中没有出现在另一组中的成员。所以我会创建一个带有有效添加的 HashSet,并遍历文件中指定的值。
    【解决方案3】:

    这是使用正则表达式的可能解决方案。它从负载中提取“Accept-Additions”行,然后检查#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) {
                // ...
            }
        }
    }
    

    第一个正则表达式从请求中提取相关行。第二个提取键值对。请注意以下注意事项:

    • 此方法无法正确提取格式错误的请求 - 只有无效的“密钥”。

    • 如果您允许不同的大小写(例如“ACCEPT-ADDITIONS”、“accept-additions”),请添加 Pattern.CASE_INSENSITIVE 标志,即Pattern.MULTILINE &amp; Pattern.CASE_INSENSITIVE

    【讨论】:

    • 我已经试用了您的代码,但是当我尝试从客户端发送字符串时收到 IllegalStateException。
    • 异常信息是什么?
    • 我假设第一个正则表达式不匹配。我稍微放松了一些 - 并添加了一个“警告”列表......
    猜你喜欢
    • 2020-08-21
    • 2019-11-28
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多