2010-04-01 13 views
5

Voglio eseguire alcuni script SQL utilizzando il metodo Runtime.exec di Java. Intendo invocare mysql.exe/mysql.sh e reindirizzare il file di script a questo processo. Dal prompt dei comandi posso eseguire il comandocome reindirizzare lo stdin in java Runtime.exec?

<mysqInstallDir\/bin\mysql.exe -u <userName> -p <password> < scripts\create_tables.sql 

posso invocare mysql.exe utilizzando Runtime.exec ma come faccio a reindirizzare i dati da file sql per mysql.exe?


ho letto l'articolo in http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4 e utilizzato il meccanismo StreamGobbler per ottenere i flussi di errore e di uscita. Nessun problema lì. Il problema arriva leggendo il file "scripts \ create_tables.sql" usando BufferedReader e passando il contenuto all'output di prcess. Mi aspettavo che il processo passasse i dati a mysql.exe. Ma vedo che solo la prima riga viene letta da questo file sql.

OutputStream outputstream = proc.getOutputStream(); 
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream); 
BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter); 
    while ((line = br.readLine()) != null) 
    { 
bufferedwriter.write(line); 
bufferedwriter.flush(); 
System.out.println(line); 
    } 
    bufferedwriter.flush(); 
    bufferedwriter.close(); 
    proc.waitFor() 

Quando faccio questo vedo che viene eseguita solo la prima riga in create_tables.sql. Il codice di uscita per il processo è 0 e non vi sono altri errori o output.

risposta

5

Exec restituisce un oggetto Processo.

Il processo ha metodi getInputStream e getOutputStream.

Basta usare quelli per afferrare il flusso di input e iniziare a spingere i byte in esso. Non dimenticare di leggere il flusso di output o il processo potrebbe bloccarsi.

+0

E il flusso di errore, naturalmente. Oppure unisci output e flussi di errore con il metodo redirectErrorStream (booleano) di ProcessBuilder e leggi i flussi uniti. –

1

Il reindirizzamento è una funzionalità degli ambienti OS shell/cmd. Per invocarli correttamente dovremmo usare Runtime.exec (String []) invece di Runtime.exec (String). Ecco il codice.

public Result executeCmd(String[] cmds, boolean waitForResult) 
{ 
    Result result = new Result(); 
    result.output = ""; 
    try 
    { 
     for(int i=0;i<cmds.length;i++) 
     { 
      System.out.println("CMD["+i+"]::"+cmds[i]); 
     } 
     System.out.println(""); 
     Process process = null; 
     if(cmds.length > 1) 
      process=Runtime.getRuntime().exec(cmds); 
     else 
      process=Runtime.getRuntime().exec(cmds[0]); 
     if (waitForResult) 
     { 
      StreamGobbler errordataReader = new StreamGobbler(process 
        .getErrorStream(), "ERROR"); 

      StreamGobbler outputdataReader = new StreamGobbler(process 
        .getInputStream(), "OUTPUT"); 

      errordataReader.start(); 
      outputdataReader.start(); 

      int exitVal = process.waitFor(); 
      errordataReader.join(); 
      outputdataReader.join(); 
      result.returnCode = exitVal; 
      result.output = outputdataReader.output; 
      result.error = errordataReader.output; 
     } 
    } 
    catch (Exception exp) 
    { 
     result.exp = exp; 
     result.returnCode = -1; 
    } 
    return result; 
} 

E chiamare questo metodo che utilizza

Result result = executeCmd(cmds, true); 

dove

CMD[0]::cmd 
CMD[1]::/c 
CMD[2]::.\mysql\bin\mysql --host=<hostname> --port=<portNum> -u <userName> < .\scripts\create_tables.sql