2011-02-08 16 views
6

Bu garip ses başlığı başlığı için özür dileriz ...Akışa "enter tuşuna bas" nasıl yazılır?

Aşağıdaki durumum var: Java programımın harici bir konsolla etkileşim kurmasını istiyorum. Bireysel komutları bu konsola "göndermek" için, normal bir konsoldaki "tuşa basılan tuş" neyin benzerini taklit etmem gerekiyor. Ne istediğimi açıklığa kavuşturmak için, mysql'in başka bir API'si olmadığını ve konsol aracılığıyla etkileşimde bulunmam gerektiğini düşünün. Bu benim asıl sorunum olmasa da, yeterince yakın.

Aşağıdaki kod var: out.close() çağrısı çalıştırılırsa

 String command = "/usr/local/mysql/bin/mysql"; 
     Process child = Runtime.getRuntime().exec(command); 

     StreamGobbler gobbler = new StreamGobbler(child.getInputStream()); 
     gobbler.start(); 

     BufferedWriter out = new BufferedWriter(new OutputStreamWriter(child.getOutputStream())); 
     out.write("help"); 
     // here enter key needs to be pressed 
     out.flush(); 
     // out.close(); 

, her şey yolunda. Ama elbette, bu şekilde sadece tek bir komut gönderebilirim, istediğim bu değil. Ancak out.close() ihmal edilirse, diğer program komutu asla çalıştırmaz. Benim tahminim hala normal bir konsolda enter tuşuna basarak yapılacak olan "bitir" komutunu beklemesidir. out.write(System.getProperty("line.separator")); ve out.newLine(); (aynıdır) sorunu çözmez, out.write("\r\n"); ve out.write((char) 26); (EOF). Tabii ki, bu tamamen yanlış yapıyorum (yani yanlış yaklaşım) olabilir. Sonra doğru yönde bir işaretçi için minnettarım ...

Bu konuda herhangi bir yardım çok takdir.

+1

Standart çıkış ** ve ** standart hata çıkışı akışlarını tüketiyor olmalısınız. Bu akışlarda ne alıyorsunuz? –

+1

Hangi sistemdesiniz? Unix yollarını kullanıyorsunuz, ancak Windows EOF'u (Ctrl-Z = 26) denediniz mi? Unix EOF, Ctrl-D'dir (= 4), fakat kesinlikle gönderilmesi gereken doğru şey değildir. –

+0

@Mark Peters: Maalesef hata çıkış akışı için bir gobbler eklemeliydim, ancak out.close() işlevi işaret edildiği gibi yürütüldüğü sürece her iki akış da hiçbir şey almamalı. @Sergey Tachenov: Bir Mac üzerinde çalışıyorum ve Ctrl-D de çalışmadı, ama bunun için teşekkürler. – roesslerj

cevap

7

Aşağıdaki kod Java 1.6.0_22 kullanarak Java 1.6.0_23 ve Ubuntu 8.04 üzerinde kullanarak hem Windows 7'nin üzerinde çalışıyor Platform çizgi ayırıcıyı yazmakla aynı. Beklendiği gibi, "out:" ile önceliği basar, sonra çıkar. "\ Q" göndermezsem, o çıkış (tabii ki) değil, yine de yardım yazdırır. Platform satırı ayırıcısı yerine "\ r \ n" veya "\ r" kullanmak benim için iyi bir fikir gibi görünmüyor, çünkü böyle bir komut satırı yardımcı programları genellikle terminalden girdi almadıklarını ve yerel metin biçimindedir ("psql < script.sql" dosyasını düşünün). İyi yazılım, tüm makul satır sonlarını doğru bir şekilde tespit etmeli ve kabul etmelidir.

+0

Örneğini gönderdiğiniz için teşekkür ederiz. Temelde benden de aynısını yaptığınız için, fark büyük olasılıkla aranan süreçte veya temel işletim sistemindeki (benim durumumdaki MacOsX) veya hatta Java versiyonundadır. Ne bulabileceğimi göreceğim, cevabınız için teşekkürler! – roesslerj

+0

@roesslerj, önce stderr'i hala kontrol etmelisiniz. Yürütülmekte olan komutun normal çalışmasını engelleyen saçma bir böcek olabilir. Ya da belki de stderr'e bir çeşit uyarı yazmayı deniyor ve engelleniyor, çünkü stderr engellenmiyor ve diğer taraf (işleminiz) hiçbir şey okumamıyor. –

+0

Bu kod parçasını gönderdiğiniz için teşekkür ederiz. Kodunuzun benim için de işe yaradığı ortaya çıkıyor ... ve "StreamGobbler" sınıfının ihmal edilmiş kodunda aptalca bir hatam oldu (hem stdout hem de stderr için kullandığınız öneri olarak ... Sadece bir minör remark: 'out.write (System.getProperty (" line.separator "));' out.newLine(); '. – roesslerj

0

out.write((char) 13) nedir? Bu Wikipedia makalesine bakın. Bunu senin için test etmek için yeterli kodum yok.

+0

Java'daki satır başı karakteri '\ r' ile gösterilir, bu yüzden bunu zaten denedim (metne bakın), ancak yine de giriş için teşekkürler. – roesslerj

0

Ayrıca Benim deneyim bu API

http://download.oracle.com/javase/6/docs/api/java/io/Console.html

bakarak deneyebilirsiniz, ben Süreç API itibaren bir süreç çalışıyor başka bir şey yapıyor hiç denemedim. Birden çok komutu girmek istediğiniz gibi görünüyor, bu API'nın bunu yapmanıza izin verebileceğini düşünüyorum.

DÜZENLEME: Daha fazla yardımcı olmak için üzerinde bir eğitici bulundu. olduğu)

public class Laj { 

    private static class ReadingThread extends Thread { 
    private final InputStream inputStream; 
    private final String name; 

    public ReadingThread(InputStream inputStream, String name) { 
     this.inputStream = inputStream; 
     this.name = name; 
    } 

    public void run() { 
     try { 
     BufferedReader in = new BufferedReader(
      new InputStreamReader(inputStream)); 
     for (String s = in.readLine(); s != null; s = in.readLine()) { 
      System.console().writer().println(name + ": " + s); 
     } 
     } catch (Exception e) { 
     e.printStackTrace(); 
     } 
    } 
    } 

    public static void main(String[] args) throws Exception { 
    String command = "psql -U archadm arch"; 
    final Process child = Runtime.getRuntime().exec(command); 
    new ReadingThread(child.getInputStream(), "out").start(); 
    new ReadingThread(child.getErrorStream(), "err").start(); 
    BufferedWriter out = new BufferedWriter(
     new OutputStreamWriter(child.getOutputStream())); 
    out.write("\\h"); 
    out.newLine(); 
    out.flush(); 
    out.write("\\q"); 
    out.newLine(); 
    out.flush(); 
    } 

} 

yeni satır (: Bu yardımcı olur http://download.oracle.com/javase/tutorial/essential/io/cl.html

Umut,

+2

Belki yanlış anlıyorum, ancak bu API, etkileşimli bir konsol kendiniz yazarken istediğiniz gibi daha fazla görünüyor. Ama yapmak istediğim bu değil; Böyle bir konsol ile harici bir süreç biçiminde etkileşimde bulunmak zorundayım. – roesslerj

İlgili konular