2017-12-26 22 views
1

私のマシンで実行中のプロセスの配列を構築しようとしています。これを行うには、次の2つのコマンドを使用しようとしています。JavaでWindowsタスクリストの出力を解析する

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

出力が正しく解析できないという問題があります。

最初のシナリオ

私のようなラインしている:それは、プロセスのメモリ使用量に来るとき、私は"".split(",")を使用して解析することを試みてきた

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

が、しかし、これは失敗した - でコンマnumberフィールドは余分なフィールドになります。私はしかし、この1つは、今System Idle Processのようなプロセスに失敗し"".split("\\s+")を使用して解析しようとしています

wininit.exe     584 Services     0  5,248 K 

2つ目のシナリオ非CSV出力なし

、私のようなラインを持っています、または実行可能な名前のスペースを持つ他のプロセス。

これらの出力のどちらかを解析して、同じ分割インデックスに常に正しいデータ列が含まれるようにするにはどうすればよいですか?

+0

コンマで区切る代わりにCSVパーサーを使用しようとしましたか? CSVは一般によく定義されており、良いパーサーは引用符を正しく解釈し、コンマごとに分割するのではありません。 – cello

+0

可能な限り少ない数の外部ライブラリを使用して、これを達成したいと思います。タスクは、最も簡単なアプローチで、最高のアプローチが何であるか不思議に思えます。 –

答えて

1

文字列を解析するには、常に最も厳密な書式設定を優先します。この場合、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); 
} 
+0

これはまさに私が探していた答えの種類です。 Yay java escapement ...正規表現を少し混乱させなければならなかった。完全で実用的な答えを作るために私自身の編集の一部で非ルビー正規表現を編集する。再度、感謝します! –

+0

よろしくお願いします! –

0

splitの代わりにStringTokenizerクラスを使用する必要があります。 "区切り文字を使用し、区切り文字が返されることを期待します。その区切り文字を使用してフィールド分離を行うことができます。たとえば、

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

各トークンはそれぞれのデータセット内に格納され、そのプロセスごとにその情報を処理できます。

0

これを試して動作するようです。

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(); 
     } 
    } 
関連する問題