国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

在java中運行其他程序詳解

2019-11-18 15:23:32
字體:
供稿:網(wǎng)友

  在java中運行其他程序詳解

由于前段時間一個網(wǎng)友寫信詢問如何在運行其他可執(zhí)行程序時將控制臺的輸入提交到它想運行的程序,由于考慮到他的非凡情況就幫他弄了一下,剛開始想著這個問題應(yīng)該比較簡單,但是在實際做的過程中才發(fā)現(xiàn)有很多陷阱,而且似乎不能弄一個非常通用的東西出來。下面的代碼是我想做出的一個通用封裝器的嘗試:

import java.io.*;public class CommandWrapper { PRocess process; Thread in; Thread out; public CommandWrapper(Process process) { this.process = process; final InputStream inputStream = process.getInputStream(); //final BufferedReader r=new BufferedReader(new InputStreamReader(inputStream)); final byte[] buffer = new byte[1024]; out = new Thread() { //String line; int lineNumber=0; public void run() { try { while (true) { int count = inputStream.read(buffer); System.out.println(lineNumber+":"+new String(buffer, 0, count-1)); //line=r.readLine(); //System.out.println(lineNumber+":"+line); lineNumber++; } } catch (Exception e) { } } }; final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); final OutputStream outputStream = process.getOutputStream(); in = new Thread() { String line; public void run() { try { while (true) { outputStream.write( (reader.readLine()+" ").getBytes()); outputStream.flush(); } } catch (Exception e) { } } }; } public void startIn() { in.start(); } public void startOut() { out.start(); } public void interruptIn() { in.interrupt(); } public void interruptOut() { out.interrupt(); } public static void main(String[] args) { try { CommandWrapper command = new CommandWrapper(Runtime.getRuntime().exec("native2ascii")); command.startIn(); command.startOut(); } catch (Exception e) { e.printStackTrace(); } }}
我以native2ascii為范例程序和網(wǎng)友給我的那個程序做了對比,發(fā)現(xiàn)如下幾個在處理這個問題時需要注重的地方:
1、由于不知道目標(biāo)程序的輸入輸出順序,因此只能建立兩個單獨的線程分別處理輸入和輸出,這樣輸入和輸出就不會阻塞了。但是有些目標(biāo)程序要求有特定的輸入輸出順序,而經(jīng)過這個類封裝的結(jié)果是在任何狀態(tài)下都可以輸入,程序的任何輸出也會被馬上反映出來。這是構(gòu)造通用類的第一個問題。
2、不能直接使用I/O重定向,在最開始的時候我是考慮直接使用I/O重定向的,但是實際的情況是Process的I/O的定義剛好和我的預(yù)想相反,我們從Process取得的InputStream實際上是它的輸出,而取得的OutputStream是它的輸入,這樣就無法進行I/O重定向了,必須我們進行編碼來讀取程序的輸出和寫入控制臺的輸入。(這里的I/O重定向是指想將它的I/O直接重定向到系統(tǒng)的I/O)
3、寫入控制臺的輸入:
outputStream.write( (reader.readLine()+" ").getBytes());
outputStream.flush();
這里有兩個問題值得注重:第一個是我們在控制臺輸入一行數(shù)據(jù)以后按下回車,那么語句reader.readLine()可以正確的得到你的輸入,為什么要加那個換行符呢?這是在測試的時候發(fā)現(xiàn)的問題,在以native2ascii作為例子的時候發(fā)現(xiàn)不加這個的話它不能得到控制臺的輸入,但是我在替那位網(wǎng)友解決的問題的時候他的程序則沒有這個問題,因此猜想可能是因為有的程序要求讀取的一整行的數(shù)據(jù)(例如native2ascii),而大部分的命令行程序在編碼的時候讀取的是整數(shù)這樣的值或者其他類型的值,他們是以空格或者其他的字符分隔的,因此就不需要那個額外的換行符(例如那位網(wǎng)友的程序讀取的是一元二次方程的三個系數(shù))。另外一個問題就是flush方法的使用,在最開始的時候沒有想到要這樣刷新進去,無論是否加換行符外部程序都無法讀取寫入的輸入,后來才想到要調(diào)用一下這個方法。這個也是在我們輸出的時候應(yīng)該注重的一個問題,有些需要馬上反應(yīng)出來的輸出一般都在寫入以后要調(diào)用它,否則輸出/輸入不能馬上反應(yīng)出來。
4、對于程序的輸出,最開始我是構(gòu)造的一個BufferedReader想以行為單位輸出,對于那位網(wǎng)友的程序,結(jié)果證實不是很好用,但是以native2ascii作為例子運行又沒有問題。這個估計和外部程序的代碼也有關(guān)系,假如外部程序沒有輸出換行符可能使用BufferedReader就會有問題。但是通過直接讀取輸出就沒有問題了。另外需要注重的就是 System.out.println(lineNumber+":"+new String(buffer, 0, count-1));
中嚴(yán)格來說應(yīng)該是:
System.out.println(lineNumber+":"+new String(buffer, 0, count));
之所以減一是因為讀取輸入的時候人為的多加了一個換行符,假如這個地方不減一就會多輸出一個空行。

基于以上的種種原因,要構(gòu)造一個執(zhí)行外部程序的包裝器類不太好辦,非凡是文章中提到的幾個問題。有時間和愛好的朋友可以做一下測試,看看以上的問題和猜測是否正確。
另外附上網(wǎng)友的源代碼,是一個fortran的程序:
implicit none
real a,b,c
real d
real root1,root2
print*,′請輸入一元二次方程的系數(shù)a,b,c:′
read(*,*) a,b,c
d=b**2-4.0*a*c
if(d>=0.0) then
root1=(-b+sqrt(d))/(2.0*a)
root2=(-b-sqrt(d))/(2.0*a)
print*,′root1=′,root1
print*,′root2=′,root2
else
print*,′一元二次方程沒有實根!′
end if
pause
end

在最開始給出的那個類雖然在某些應(yīng)用中可能存在問題,但是對于一般的程序可能問題不是很大,當(dāng)然大家可以根據(jù)上面的說明、猜測在應(yīng)用在自己的項目中的時候進行一些修改和測試。假如最終有什么結(jié)論請和大家分享。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 社会| 华安县| 长子县| 班玛县| 武城县| 南溪县| 贺兰县| 游戏| 桃园市| 大渡口区| 保山市| 保定市| 土默特右旗| 翁牛特旗| 昌邑市| 枣阳市| 岳阳市| 新郑市| 安阳市| 遵义市| 车险| 阳信县| 阿克陶县| 宜春市| 旬阳县| 旺苍县| 中江县| 祥云县| 宁远县| 茌平县| 新巴尔虎右旗| 西丰县| 武安市| 民和| 卢氏县| 柳林县| 绍兴市| 潜江市| 镇巴县| 乌鲁木齐市| 四平市|