有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

gwt Java ProcessBuilder如何获取实时输出

我有一个正在成功运行的ProcessBuilder,它在服务器上扫描DVB-T的频道广播,我希望输出到一个网页

服务器代码如下所示:

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

通过RPC调用从GWT客户端开始扫描。为简洁起见,以下是代码:

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或其他什么


共 (1) 个答案

  1. # 1 楼答案

    经过两天的努力,我终于在半小时后找到了答案。Grr

    我更改了这个以获取错误流:

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

    在服务器函数scanByBroadcaster()中,我刚刚添加了return true,这使客户端计时器能够开始轮询