【问题标题】:Parsing Windows tasklist output in Java在 Java 中解析 Windows 任务列表输出
【发布时间】:2017-12-26 19:36:11
【问题描述】:

我正在尝试构建在我的机器上运行的一系列进程;为此,我一直在尝试使用以下两个命令:

tasklist /fo csv /nh        # For a CSV output
tasklist /nh                # For a non-CSV output

我遇到的问题是我无法正确解析输出。

第一个场景

我有这样一行:

"wininit.exe","584","Services","0","5,248 K"

我曾尝试使用 "".split(",") 进行解析,但是在进程内存使用方面失败了 - 数字字段中的逗号将导致一个额外的字段。

第二种情况

没有非 CSV 输出,我有这样一行:

wininit.exe                    584 Services                   0      5,248 K

我正在尝试使用 "".split("\\s+") 解析它,但是现在这个在 System Idle Process 之类的进程上失败,或者在可执行文件名称中有空格的任何其他进程上失败。

如何解析这些输出中的任何一个,以便相同的拆分索引始终包含正确的数据列?

【问题讨论】:

  • 您是否尝试过使用 CSV 解析器而不是仅在逗号上拆分? CSV 通常定义良好,良好的解析器可以正确解释引号,而不是在每个逗号处拆分。
  • 我希望使用尽可能少的外部库来实现这一点,最好不要。这项任务似乎很简单,只是想知道最好的方法是什么。

标签: java string windows split tasklist


【解决方案1】:

要解析字符串,总是首选最严格的格式。在这种情况下,CSV。这样,您可以使用包含五个组的正则表达式处理每一行:

private final Pattern pattern = Pattern
    .compile("\\\"([^\\\"]*)\\\",\\\"([^\\\"]*)\\\",\\\"([^\\\"]*)\\\",\\\"([^\\\"]*)\\\",\\\"([^\\\"]*)\\\"");

private void parseLine(String line) {

    Matcher matcher = pattern.matcher(line);

    if (!matcher.find()) {
        throw new IllegalArgumentException("invalid format");
    }

    String name = matcher.group(1);
    int pid = Integer.parseInt(matcher.group(2));
    String sessionName = matcher.group(3);
    String sessionId = matcher.group(4);
    String memUsage = matcher.group(5);

    System.out.println(name + ":" + pid + ":" + memUsage);
}

【讨论】:

  • 这正是我正在寻找的答案。耶 java 擒纵系统...不得不稍微弄乱正则表达式。使用我自己的一些编辑在非 ruby​​ 正则表达式中进行编辑,以做出完整且有效的答案。再次感谢!
【解决方案2】:

您应该使用 StringTokenizer 类而不是 split。您使用 " 分隔符并期望返回分隔符。然后,您可以使用该分隔符来提供字段分隔。例如,

StringTokenizer st = new StringTokenizer(input, "\"", true);

State state = NONE;

while (st.hasMoreTokens()) {
    String t = st.nextToken();
    switch(state) {
       case NONE:
          if ("\"".equals(t)) {
             state = BEGIN;
          }
          // skip the ,
          break;
       case BEGIN:
          // Store t in which entry it correspond to.
          state = END;
          break;
       case END:
          state = NONE;
          break;
    }
}

每个令牌都将存储在其各自的数据集中,然后您可以为每个进程处理该信息。

【讨论】:

    【解决方案3】:

    试过了,好像还可以。

     public void parse(){
            try {
                Runtime runtime = Runtime.getRuntime();
                Process proc = runtime.exec("tasklist -fo csv /nh");
                BufferedReader stdInput = new BufferedReader(new
                        InputStreamReader(proc.getInputStream()));
                String line = "";
                while ((line = stdInput.readLine()) != null) {
                    System.out.println();
                    for (String column: line.split("\"")){
                        if (!column.equals(",")&& !column.equals("")){
                            System.out.print("["+column+"]");
                        }
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-12
      • 1970-01-01
      相关资源
      最近更新 更多