我正在尝试构建一个在我的机器上运行的进程数组;这样做我一直在尝试使用以下两个命令:
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。这样,您可以使用包含FIVE组的正则表达式处理每一行:
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);
}
您应该使用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;
}
}
每个令牌将存储在其各自的数据集中,然后您可以为每个进程处理该信息。
试过这个似乎工作。
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();
}
}