java調(diào)用Oracle EXP備忘

          一眼看過去相信大家都知道用Runtime.getRuntime().exec來調(diào)用,我的需求就是:
          調(diào)用Oracle EXP命令完成備份,并返回生成的備份文件名,這個備份文件會很快在其他的地方被使用。
          采用Runtime.getRuntime().exec我們都知道,需要處理它的InputStream,以避免出現(xiàn)執(zhí)行的命令輸出的信息過多使得進程被堵死,OK,按照這樣的方法,開寫:

          String[]?cmds? = ? new ?String[ 3 ];
          cmds[
          0 ]? = ? " cmd " ;
          cmds[
          1 ]? = ? " /C " ;
          cmds[
          2 ] = "exp username/password@sid file=xxx.dmp log=xxx.log";
          ??? Process?process
          = Runtime.getRuntime().exec(cmds);
          ????????
          try ? {
          ????????????InputStreamReader?isr?
          = ? new ?InputStreamReader(process.getInputStream());
          ????????????BufferedReader?br?
          = ? new ?BufferedReader(isr);
          ????????????String?line?
          = ? null ;
          ????????????
          while ?((line? = ?br.readLine())? != ? null ) {
          ????????????????System.out.println(line);????????????
          ?????????????????? }

          ????????}
          ?
          ????????
          catch ?(IOException?ioe)? {
          ????????????????ioe.printStackTrace();

          ????????}
          寫完收工,執(zhí)行,傻了,進程被掛S了,到底什么原因呢,開始瞎嘗試,把讀取process的InputStream的部分全部去掉,執(zhí)行,竟然OK,更暈,但這個時候出現(xiàn)了一個問題,那就是沒法知道什么時候備份文件完全生成了,如果在Runtime.getRuntime后去獲取備份文件,那個時候甚至連備份文件都沒生成,之后甚至嘗試過輪詢直到備份文件生成,再往下走,那樣還是有問題,就是生成的那個備份文件永遠都只有正常的一半的大小,只有在整個進程退出的時候它才正常的全部生成。
          竟然碰到這樣的問題,徹底暈,開始google,竟然只查到一篇和我這同樣的問題,更郁悶的是那個帖子最后樓主寫了一句“問題解決了”,但沒寫是怎么解決的,郁悶S。
          只好自己開始嘗試各種辦法,上網(wǎng)抓人到處問,最后在自己不斷的嘗試下終于是出現(xiàn)了轉機,在我的N+1次嘗試的時候我改為只讀取process的ErrorStream,然后執(zhí)行,暈,OK了,在導出成功的情況下沒有問題,但在導出有錯誤的時候(像sid不對,用戶名錯誤,數(shù)據(jù)庫沒啟動等)進程還是被掛S,但只要導出成功沒問題,導出有錯誤的問題是很好處理的,OK,最后試驗的代碼改為這樣:
          String[]?cmds?=?new?String[3];
          ????????cmds[
          0]?=?"cmd";
          ????????cmds[
          1]?=?"/C";
          ????????cmds[
          2]=commandBuf.toString();
          ????????Process?process
          =Runtime.getRuntime().exec(cmds);
          ????????
          boolean?shouldClose=false;
          ????????
          try?{
          ????????????InputStreamReader?isr?
          =?new?InputStreamReader(process.getErrorStream());
          ????????????BufferedReader?br?
          =?new?BufferedReader(isr);
          ????????????String?line?
          =?null;
          ????????????
          while?((line?=?br.readLine())?!=?null){
          ????????????????
          if(line.indexOf("錯誤")!=-1){
          ????????????????????shouldClose
          =true;
          ????????????????????
          break;
          ????????????????}

          ????????????}

          ????????}
          ?
          ????????
          catch?(IOException?ioe)?{
          ????????????shouldClose
          =true;
          ????????}

          ????????
          if(shouldClose)
          ????????????process.destroy();
          ????????
          int?exitVal?=?process.waitFor();
          當然,實際的代碼中不能像這里寫的一樣,直接去判斷是否含錯誤這個字符串,而且這段代碼是只適合在winnt版本以上的windows操作系統(tǒng)上執(zhí)行的。
          這樣反而可以了,說明什么呢,說明在執(zhí)行oracle的exp時,出現(xiàn)了一個很怪的現(xiàn)象,就是exp在console輸出的信息沒有被放入InputStream,反而是放到了ErrorStream中(即使正確的情況也是),這就導致了按照正常的情況去寫這段代碼的話反而會出問題。

          擔心以后再次碰到這樣的問題,備忘一下....

          posted on 2006-11-22 22:43 BlueDavy 閱讀(7750) 評論(8)  編輯  收藏 所屬分類: Java

          評論

          # re: java調(diào)用Oracle EXP備忘 2006-11-23 13:09 javabeginer

          從沒寫過有關process的東西,學習!  回復  更多評論   

          # re: java調(diào)用Oracle EXP備忘 2006-11-24 14:38 kruce[匿名]

          正如你所說的,處理Process的時候要注意及時讀取子進程的輸出流,不然可能導致子進程堵塞,甚至死鎖。
          如果我是你,我會這么來排除bug。
          1,把對InputStream的處理放到一個單獨Thread里面。
          2,用ProcessBuilder的redirectErrorStream來合并OutputStream和ErrorStream。注意子進程的InputStream對應父進程的OutStream。如果不合并這兩個流的話則必須并行排空它們,順序的排空會導致思索。
          建議你好好看看5.0的API和JLS。  回復  更多評論   

          # re: java調(diào)用Oracle EXP備忘 2006-11-24 21:34 BlueDavy

          @kruce[匿名]
          ....我用的是1.4....雖然我也很想用5.0的ProcessBuilder  回復  更多評論   

          # re: java調(diào)用Oracle EXP備忘 2007-01-11 16:41 roygbip

          我也遇到你這樣的問題,不過我還是用getInputStream()才可以,用getErrorStream我也試了一下,只能倒入300條數(shù)據(jù)就卡住了.  回復  更多評論   

          # re: java調(diào)用Oracle EXP備忘 2007-04-26 17:10 lq

          我今天遇到這個問題了  回復  更多評論   

          # re: java調(diào)用Oracle EXP備忘 2007-05-28 16:56 lift

          Win的控制臺程序和UNIX下的命令執(zhí)行完畢后,都會有一個出口值(EXIT CODES),如果執(zhí)行成

          功的話,這個值一般為0,不成功則為其它值。在Windows下,可以在程序執(zhí)行完畢后,馬上輸入

          echo %ERRORLEVEL%查看這個值;在Unix下則是輸入 echo $?。實質(zhì)上都是保存在一個環(huán)境變量

          中。

          在Java中通過Process來運行外部程序的時候,可以調(diào)用Process的exitValue()方法來獲得程序

          的出口值。Oracle的exp和imp在各種情況下的出口值如下:
          A. Successful export/import.
          -------------------------
          Result : Export terminated successfully without warnings
          Import terminated successfully without warnings
          Exit Code : EX_SUCC
          Exit Level: 0

          B. Successful export/import with warnings.
          ---------------------------------------
          Result : Export terminated successfully with warnings
          Import terminated successfully with warnings
          Exit Code : EX_OKWARN
          Exit Level: 0 (for Unix platforms)
          1 (for Windows platform with Oracle9i, Oracle8i, and below)
          3 (for Windows platform with Oracle10g and higher)

          C. Unsuccessful export/import.
          ---------------------------
          Result : Export terminated unsuccessfully
          Import terminated unsuccessfully
          Exit Code : EX_FAIL
          Exit Level: 1 (for Unix platforms, and for Windows platforms with
          Oracle10g and higher)
          3 (for Windows platform with Oracle9i, Oracle8i, and below)
            回復  更多評論   

          # re: java調(diào)用Oracle EXP備忘 2007-05-28 17:07 lift

          exp和imp的輸出是要從ErrorStream中獲取,這是我以前寫的
          Process proc = null;
          try
          {
          proc = Runtime.getRuntime().exec(cmd.toString());
          InputStream istr = proc.getErrorStream();
          BufferedReader br = new BufferedReader(new InputStreamReader(istr));
          String str;
          while ((str=br.readLine()) != null)
          {
          errorInfo.append(str + "\n");
          }
          proc.waitFor();
          }
          catch (Exception e)
          {
          ...
          }
          if (proc.exitValue() == 0)
          {
          proc.destroy();
          return true;
          }
          else
          {
          if(logger.isDebugEnabled())
          logger.debug(errorInfo);
          proc.destroy();
          return false;
          }  回復  更多評論   

          # re: java調(diào)用Oracle EXP備忘 2008-02-28 17:10 leonranri

          非常感謝這篇文章,著實很難解決  回復  更多評論   

          公告

           









          feedsky
          抓蝦
          google reader
          鮮果

          導航

          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          統(tǒng)計

          隨筆分類

          隨筆檔案

          文章檔案

          Blogger's

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 巴彦县| 凤阳县| 喀喇沁旗| 楚雄市| 广昌县| 土默特左旗| 大悟县| 蓝田县| 和静县| 全南县| 郸城县| 华池县| 绥芬河市| 建阳市| 尤溪县| 都匀市| 紫阳县| 余庆县| 县级市| 平谷区| 临洮县| 兴山县| 左权县| 工布江达县| 青河县| 西充县| 临颍县| 建宁县| 大理市| 从化市| 洪泽县| 舟曲县| 宜春市| 宜宾县| 塔城市| 苏尼特左旗| 尼勒克县| 农安县| 天门市| 新乡县| 淳化县|