Swing


          天行健 君子以自強不息

          posts - 69, comments - 215, trackbacks - 0, articles - 16
             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          java調用Oracle EXP備忘

          Posted on 2007-05-18 09:31 zht 閱讀(457) 評論(0)  編輯  收藏 所屬分類: J2se

          一眼看過去相信大家都知道用Runtime.getRuntime().exec來調用,我的需求就是:
          調用Oracle EXP命令完成備份,并返回生成的備份文件名,這個備份文件會很快在其他的地方被使用。
          采用Runtime.getRuntime().exec我們都知道,需要處理它的InputStream,以避免出現執行的命令輸出的信息過多使得進程被堵死,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();

                  }
          寫完收工,執行,傻了,進程被掛S了,到底什么原因呢,開始瞎嘗試,把讀取process的InputStream的部分全部去掉,執行,竟然OK,更暈,但這個時候出現了一個問題,那就是沒法知道什么時候備份文件完全生成了,如果在Runtime.getRuntime后去獲取備份文件,那個時候甚至連備份文件都沒生成,之后甚至嘗試過輪詢直到備份文件生成,再往下走,那樣還是有問題,就是生成的那個備份文件永遠都只有正常的一半的大小,只有在整個進程退出的時候它才正常的全部生成。
          竟然碰到這樣的問題,徹底暈,開始google,竟然只查到一篇和我這同樣的問題,更郁悶的是那個帖子最后樓主寫了一句“問題解決了”,但沒寫是怎么解決的,郁悶S。
          只好自己開始嘗試各種辦法,上網抓人到處問,最后在自己不斷的嘗試下終于是出現了轉機,在我的N+1次嘗試的時候我改為只讀取process的ErrorStream,然后執行,暈,OK了,在導出成功的情況下沒有問題,但在導出有錯誤的時候(像sid不對,用戶名錯誤,數據庫沒啟動等)進程還是被掛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操作系統上執行的。
          這樣反而可以了,說明什么呢,說明在執行oracle的exp時,出現了一個很怪的現象,就是exp在console輸出的信息沒有被放入InputStream,反而是放到了ErrorStream中(即使正確的情況也是),這就導致了按照正常的情況去寫這段代碼的話反而會出問題。

          擔心以后再次碰到這樣的問題,備忘一下....
          posted on 2006-11-22 22:43 BlueDavy 閱讀(1593) 評論(5)  編輯 收藏 引用 所屬分類: Java

          評論

          # re: java調用Oracle EXP備忘 2006-11-23 13:09 javabeginer
          從沒寫過有關process的東西,學習!  回復  更多評論
            

          # re: java調用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調用Oracle EXP備忘 2006-11-24 21:34 BlueDavy
          @kruce[匿名]
          ....我用的是1.4....雖然我也很想用5.0的ProcessBuilder  回復  更多評論
            

          # re: java調用Oracle EXP備忘 2007-01-11 16:41 roygbip
          我也遇到你這樣的問題,不過我還是用getInputStream()才可以,用getErrorStream我也試了一下,只能倒入300條數據就卡住了.  回復  更多評論
          主站蜘蛛池模板: 汶上县| 遂川县| 苍溪县| 茶陵县| 邵阳县| 景东| 纳雍县| 合阳县| 仁化县| 富源县| 南开区| 客服| 康乐县| 嵩明县| 洪洞县| 南乐县| 张家川| 格尔木市| 阿荣旗| 镇安县| 外汇| 乐安县| 武平县| 辰溪县| 新巴尔虎左旗| 康定县| 金阳县| 冷水江市| 万山特区| 喜德县| 怀集县| 闻喜县| 古交市| 习水县| 邮箱| 巴塘县| 九龙城区| 屏山县| 霸州市| 北宁市| 玉龙|