Java'da konsoldan tek bir karakter nasıl okunur (kullanıcı yazarken)?


110

Kullanıcı Java'da yazarken konsoldan tek bir karakter okumanın kolay bir yolu var mı? Mümkün mü? Bu yöntemleri denedim ama hepsi kullanıcının enter tuşuna basmasını bekliyor:

char tmp = (char) System.in.read();
char tmp = (char) new InputStreamReader(System.in).read ();
char tmp = (char) System.console().reader().read();           // Java 6

Enter tuşuna basılıncaya kadar System.in'in kullanıcı girişinden haberdar olmadığını düşünmeye başladım .

Yanıtlar:


57

Yapmak istediğiniz şey konsolu, "pişmiş" modun aksine (satır düzenleme baypas edilmiş ve giriş anahtarı gerekmez) "ham" moda koymaktır (enter tuşu ile satır düzenleme gerekir.) UNIX sistemlerinde, "stty" komutu, modları değiştirin.

Şimdi, Java ile ilgili olarak ... Python ve Java'da engellemesiz konsol girişine bakın . Alıntı:

Programınızın konsol tabanlı olması gerekiyorsa, terminalinizi hat dışı modunu karakter moduna geçirmeniz ve programınız kapanmadan önce onu geri yüklemeyi unutmayın. Bunu işletim sistemlerinde yapmanın taşınabilir bir yolu yoktur.

Önerilerden biri JNI kullanmaktır. Yine, bu çok taşınabilir değil. İleti dizisinin sonundaki ve yukarıdaki gönderi ile ortak olan bir başka öneri, jCurses kullanımına bakmaktır .


4
JCurses da çok taşınabilir değildir .... JCurses README'den: "JCurses iki bölümden oluşur: platform bağımsız parça ve ilk parça için ilkel girdi ve çıktı işlemlerini mümkün kılan yerel bir paylaşılan kitaplıktan oluşan platform bağımlı bölüm . "
Ryan Fernandes

6
@RyanFernandes kulağa oldukça taşınabilir geliyor - birden fazla sistemde çalıştırılabilen tek bir araç (farklı bağımlılıklar kullanarak)
Antoniossss 19'17

25

Konsolunuzu ham moda geçirmeniz gerekiyor. Oraya ulaşmanın yerleşik platformdan bağımsız bir yolu yoktur. Yine de jCurses ilginç olabilir.

Bir Unix sisteminde bu işe yarayabilir:

String[] cmd = {"/bin/sh", "-c", "stty raw </dev/tty"};
Runtime.getRuntime().exec(cmd).waitFor();

Örneğin, tuş vuruşları arasındaki süreyi hesaba katmak istiyorsanız, oraya ulaşmak için işte örnek kod.


Linux altında benim için iyi çalıştı
MrSmith42

4
Mac'te de çalıştı. Muhtemelen stty cooked </dev/tty, programın arabelleğe alınmış moda dönmesi gerektiğinde ve kesinlikle program çıkmadan önce çalıştırılması gerektiğini belirtmek istersiniz .
Kelvin

15

Bir Java konsolundan ham karakterleri okumanın taşınabilir bir yolu yoktur.

Platforma bağlı bazı geçici çözümler yukarıda sunulmuştur. Ancak gerçekten taşınabilir olmak için, konsol modunu terk etmeniz ve örneğin AWT veya Swing gibi bir pencere modu kullanmanız gerekir.


22
Örneğin Mono (veya CLR) 'nin System.Console.ReadKeytüm platformlarda çalışan hangisine sahip olduğunu tam olarak anlamıyorum . Java ayrıca her platform için JVM ve JRE'yi platforma bağlı kitaplıklar ve uygulamalarla dağıtır, bu nedenle bu bir mazeret değildir.
Martin Macak

13

Windows ve Unix / Linux işletim sistemi işlevlerini çağırmak için JNA kullanan bir Java sınıfı RawConsoleInput yazdım .

  • Windows'ta Kullandığı _kbhit()ve _getwch()msvcrt.dll gelen.
  • Unix'te tcsetattr(), konsolu kanonik olmayan moda System.in.available()geçirmek , verilerin mevcut olup olmadığını kontrol etmek System.in.read()ve konsoldan baytları okumak için kullanır. A CharsetDecoder, baytları karakterlere dönüştürmek için kullanılır.

Engellemeyen girişi ve ham modu ve normal hat modu girişini karıştırmayı destekler.


Bu ne kadar yoğun bir şekilde test edildi / stres testi yapıldı?
Fon Monica'nın Davası

2
@QPaysTaxes Konsol girişi için stres testi zordur. Sanırım bu durumda çeşitli ortamlarda (farklı Windows / Linux sürümleri, 64/32 bit, SSH üzerinden Linux, Telnet, seri bağlantı noktası veya masaüstü konsolu vb.) Test etmenin daha önemli olacağını düşünüyorum. Şimdiye kadar sadece özel test araçlarımda kullanıyorum. Ancak kaynak kodu, diğer çözümlere kıyasla (Jansi kullanan JLine2 gibi) nispeten küçüktür. Yani yanlış gidebilecek pek bir şey yok. Ben yazdım çünkü JLine2 engellemeden tek karakter girişi desteklemiyor.
Christian d'Heureuse

Stres testi ile kastettiğim buydu - muhtemelen yanlış kelime; benim hatam. Her neyse, güzel! ^ H ^ H ^ H ^ H ^ H ^ Onu okul için yaptığım bir projede çaldım ve bir grup yardımcı oldu.
Fund Monica'nın Davası

Hey - bu ders harika görünüyor. Ancak: Çalışmasını sağlayamıyorum .. Nasıl kullanacağım? CTRL + D'ye (Linux'ta) basana kadar System.in engellemeyle karşılaştım ve şimdi konsol modları ve beğenileri hakkında okuyorum. Sanırım RawConsoleInput aradığım şey - ama onu nasıl kullanırım?
Igor

@Igor Bir klavye karakterini okumak için RawConsoleInput.read (boolean) 'ı çağırmanız yeterlidir. Kaynak kodunda (RawConsoleInput.java) belgelenmiştir.
Christian d'Heureuse

8

Jline3 kullanın :

Misal:

Terminal terminal = TerminalBuilder.builder()
    .jna(true)
    .system(true)
    .build();

// raw mode means we get keypresses rather than line buffered input
terminal.enterRawMode();
reader = terminal .reader();
...
int read = reader.read();
....
reader.close();
terminal.close();

RawConsoleInput tabanlı çözümlerin MacOS High Sierra'da çalışmadığını buldum; ancak bu mükemmel çalışıyor.
RawToast

jline, etkileşimli bir konsol / terminal sistemi oluşturmak için ihtiyacınız olan her şeye sahiptir. Linux'ta harika çalışıyor. Daha eksiksiz bir örnek için şu adrese bakın: github.com/jline/jline3/blob/master/builtins/src/test/java/org/… . Otomatik tamamlama, geçmiş, şifre maskesi vb. Var
lepe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.