在 Java 中解析 Windows 任务列表输出

Parsing Windows tasklist output in Java

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

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 之类的进程或任何其他可执行文件名称中带有 space 的进程上失败。

How can I parse either of these output such that the same split index will always contain the correct data column?

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

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;
    }
}

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

试过这个似乎有效。

 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();
        }
    }

要解析一个字符串,总是喜欢最严格的格式。在这种情况下,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);
}