2016-11-24 197 views
0

我有一個成功運行的ProcessBuilder,它正在運行掃描DVB-T以在服務器上進行頻道廣播,我希望輸出進入網頁。Java ProcessBuilder如何獲取實時輸出

服務器代碼如下:

private static StringBuilder scan_output = null; 
private static String scan_result = ""; 

@Override 
public boolean scanByBroadcaster(String user, String broadcaster) { 
    UserAccountPermissions perm = validateUserEdit(user); // allowed to run scan? 
    if (perm == null) return false; 

    String[] commands = { 
      "/usr/bin/scan", 
      dvbDir + broadcaster, 
      "-o", 
      "zap", 
      "-U", 
      "-q", 
      "-a", 
      "5", 
      ">", 
      LoginConstants.loc_dvb_scanfile 
    }; 

    System.out.println("Scan by broadcast: " + broadcaster); 

    scan_output = new StringBuilder(); 
    new ScanThread(commands).start(); 

    return false; 
} 

// runs the scan independant and the IO capture 
private static class ScanThread extends Thread { 
    String[] commands = null; 
    public ScanThread(String[] commands) { 
     this.commands = commands; 
    } 
    public void run() { 
     ProcessBuilder pb = new ProcessBuilder(commands); 
     Process process; 
     try { 
      System.out.println("Scan thread running"); 
      process = pb.start(); 
      IOScanOutputHandler handler = new IOScanOutputHandler(process.getInputStream()); 
      handler.start(); 
      process.waitFor(); 
     } catch (IOException e) { 
      System.out.println(e.getMessage()); 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      System.out.println(e.getMessage()); 
      e.printStackTrace(); 
     } 
     //scan_output = null; 
     System.out.println("Scan thread finished"); 
    } 
} 

// background thread to capture output of scan (as it arrives) 
// this only captures the final scan results though 
private static class IOScanOutputHandler extends Thread { 
    private InputStream inputStream; 

    IOScanOutputHandler(InputStream inputStream) { 
     this.inputStream = inputStream; 
    } 

    public void run() { 
     Scanner br = null; 
     try { 
      System.out.println("Scan thread IO capture running"); 
      br = new Scanner(new InputStreamReader(inputStream)); 
      String line = null; 
      while (br.hasNextLine()) { 
       line = br.nextLine(); 
       scan_output.append(line + System.getProperty("line.separator")); 
      } 
     } finally { 
      br.close(); 
     } 
     System.out.println("Scan thread IO capture finished"); 
     scan_result = scan_output.toString(); 
     scan_output = null; 
    } 
} 

// polled by web interface every second 
@Override 
public String pollScanResult(String user) { 
    if (validateUserEdit(user) == null) return null; 
    StringBuilder sb = scan_output; // grab instance 
    if (sb == null) return null; 
    return sb.toString(); 
} 

最終輸出其實我得到的是什麼進入「LoginConstants.loc_dvb_scanfile」,而不是這樣的輸出:

ERROR: invalid enum value '7378' 
ERROR: invalid enum value '3300' 
ERROR: invalid enum value '0' 
ERROR: invalid enum value '8MHz' 
ERROR: invalid enum value '2/3' 
ERROR: invalid enum value 'NONE' 
ERROR: invalid enum value 'QAM2' 
>>> tune to: 706000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_2_3:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE 
>>> tune to: 778000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_2_3:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE 
>>> tune to: 2:INVERSION_AUTO:BANDWIDTH_AUTO:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO 
__tune_to_transponder:1910: ERROR: Setting frontend parameters failed: 22 Invalid argument 
>>> tune to: 2:INVERSION_AUTO:BANDWIDTH_AUTO:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO 
__tune_to_transponder:1910: ERROR: Setting frontend parameters failed: 22 Invalid argument 
>>> tune to: 770000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE 
>>> tune to: 698000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE 
>>> tune to: 746000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE 
>>> tune to: 762000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_16:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE 
WARNING: filter timeout pid 0x0011 
WARNING: filter timeout pid 0x0000 
WARNING: filter timeout pid 0x0010 

掃描會從開始GWT客戶端通過RPC調用。爲了簡便起見,下面的代碼:

private void runScanQuick() { 
    server.checkEditAccess(user, new AsyncCallback<Boolean>() { 

     @Override 
     public void onFailure(Throwable caught) { 
      log.info("runScanQuick server failure"); 
     } 

     @Override 
     public void onSuccess(Boolean result) { 
      if (result == false) return; // not allowed to run scan 

      final DialogBox dia = new DialogBox(); 
      final Frame frame = new Frame(url_base + url_ext_scanbybroadcaster); 
      frame.addLoadHandler(new LoadHandler() { 

       @Override 
       public void onLoad(LoadEvent event) { 
        String broadcaster = scan_country.getSelectedItemText() + "-" + scan_broadcaster.getSelectedItemText(); 
        log.info("Scan file: " + broadcaster); 
        Document doc = IFrameElement.as(frame.getElement()).getContentDocument(); 
        doc.getElementById("broadcaster").appendChild(new HTML(broadcaster).getElement()); 
        Button okay = Button.wrap(doc.getElementById("okay")); 
        Button cancel = Button.wrap(doc.getElementById("cancel")); 
        cancel.addClickHandler(new ClickHandler() { 

         @Override 
         public void onClick(ClickEvent event) { 
          dia.hide(); 
         } 
        }); 
        okay.addClickHandler(new ClickHandler() { 

         @Override 
         public void onClick(ClickEvent event) { 
          dia.hide(); 
          runScanQuickStart(); 
         } 
        }); 
       } 
      }); 
      frame.setSize("500px", "500px"); 
      dia.add(frame); 
      dia.setGlassEnabled(true); 
      dia.setStyleName(""); 
      dia.center(); 
      dia.show(); 
     } 
    }); 
} 

private void runScanQuickStart() { 
    final DialogBox dia = new DialogBox(); 
    final Frame frame = new Frame(url_base + url_ext_scanbroadcasterprogress); 
    frame.addLoadHandler(new LoadHandler() { 

     @Override 
     public void onLoad(LoadEvent event) { 
      Document doc = IFrameElement.as(frame.getElement()).getContentDocument(); 
      String broadcaster = scan_country.getSelectedItemText() + "-" + scan_broadcaster.getSelectedItemText(); 
      doc.getElementById("title").appendChild(new HTML(broadcaster).getElement()); 
      Button okay = Button.wrap(doc.getElementById("okay")); 
      final TextArea area = TextArea.wrap(doc.getElementById("textarea")); 
      final Timer timer = new Timer() { 
       @Override 
       public void run() { 
        server.pollScanResult(user, new AsyncCallback<String>() { 

         @Override 
         public void onFailure(Throwable caught) { 
          cancel(); 
         } 

         @Override 
         public void onSuccess(String result) { 
          if (result == null) cancel(); 
          else { 
           area.setText(result); 
          } 
          log.info("Polled for scan result"); 
         } 
        }); 
       } 
      }; 
      okay.addClickHandler(new ClickHandler() { 

       @Override 
       public void onClick(ClickEvent event) { 
        timer.cancel(); 
        dia.hide(); 
       } 
      }); 
      server.scanByBroadcaster(user, broadcaster, new AsyncCallback<Boolean>() { 

       @Override 
       public void onFailure(Throwable caught) { 
        log.info("runScanQuickStart server call failed"); 
       } 

       @Override 
       public void onSuccess(Boolean result) { 
        if (result == false) return; 
        timer.scheduleRepeating(1000); 
       } 
      }); 
     } 
    }); 
    frame.setSize("740px", "500px"); 
    dia.add(frame); 
    dia.setGlassEnabled(true); 
    dia.setStyleName(""); 
    dia.center(); 
    dia.show(); 
} 

一切從事實,我不知道如何獲取來自現場的ProcessBuilder輸出的除了做工精細。

有誰知道如何獲取實時輸出,以便我可以在網頁上顯示實時反饋?

我在想,也許它可能是stderr,stdout什麼的。

回答

0

經過兩天的努力,然後發佈一個問題,我在半小時後才發現問題。 GRR ...

我改變了這種在獲得錯誤流:

//IOScanOutputHandler handler = new IOScanOutputHandler(process.getInputStream()); 
IOScanOutputHandler handler = new IOScanOutputHandler(process.getErrorStream()); 

而在服務器功能scanByBroadcaster(),我只是說真正的回報,這使客戶端計時器開始投票。

P !!!