Input/Output Einlesen von der Konsole mit InputStreamReader

coldstone

Bekanntes Mitglied
Hallo Java Freunde,

kann mir jemand vielleicht sagen was ich bei diesem code falsch mache?

Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Eingabe {

    public static void main(String[] args) throws IOException {
      
        String kommando = textEingeben("");
        String ls = "ls";
      
     if (kommando == ls)     {
          System.out.println(ls);
      }
     else {
         System.out.println("Falsche eingabe");
     }
    }

    public static String textEingeben(String wertBez) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    
        System.out.print(">" + wertBez);
        return br.readLine();
    }
  
}

Ziel ist es die Eingabe über die konsole zu vergleichen, falls identisch eingabe wieder ausgeben lassen fals nicht identisch "Falsche eingabe" ausgeben. Aber es wird immer wieder "Falsche Eingabe" ausgegeben. Was mache ich bei dem vergleich falsch?
 
Strings werden nicht mit == sondern mit einem equals Aufruf verglichen. Bei == ist es lediglich ein Vergleich der Referenz.
Also ein if (ls.equals(kommando)) statt einem if (kommando == ls)
 
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class eingabe{

    public static void main(String[] args) throws IOException {
    
        String kommando = textEingeben("");
     
        String ls = "ls";
        String touch = "touch";
        String rm = "rm";
        String cd = "cd";
        String mv = "mv";
        String cp = "cp";
        String pwd = "pwd";
        String cat = "cat";
        String mkdir = "mkdir";
        String rmdir = "rmdir";
    
     if (kommando.equals(touch))     {
          System.out.println(touch);
      }
     if (kommando.equals(ls))     {
         System.out.println(ls);
     }
     if (kommando.equals(rm))     {
         System.out.println(rm);
     }
     if (kommando.equals(cd))     {
         System.out.println(cd);
     }
     if (kommando.equals(mv))     {
         System.out.println(mv);
     }
     if (kommando.equals(cp))     {
         System.out.println(cp);
     }
     if (kommando.equals(pwd))     {
         System.out.println(pwd);
     }
     if (kommando.equals(cat))     {
         System.out.println(cat);
     }
     if (kommando.equals(mkdir))     {
         System.out.println(mkdir);
     }
     if (kommando.equals(rmdir))     {
         System.out.println(rmdir);
     } else {
      
        System.out.println(kommando + ": command not found");
     }
    }

     
    public static String textEingeben(String wertBez) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  
        System.out.print(">" + wertBez);
        return br.readLine();
    }

}

jedesmal wenn einen der String werte einlese gibt er mir die "else" Bedingung mit aus. Wie kann ich die "else" Bedingung so einbinden, das sie für alle IF Abfragen gilt?

OK. Habe gerade gemerkt das es mit switch ja viel einfacher ist. 😀
 
Zuletzt bearbeitet:
Ja genau, hier bietet sich sein switch an. Aber der gepostete Code hat das Problem, dass das else sich nur auf das letzte if bezog. Wenn man so eine Kette an Vergleichen mit if machen will, dann wäre das Konstrukt wie folgt aufzubauen:
Code:
if (..) {
} 
else if (..) {
}
else if (..) {
}
else {
}

Durch den else Bereich nach jedem if bricht er bei einer Übereinstimmung diese Vergleichskette ab.
 
Du könntest auch eine Liste nehmen, in die Du alle deine Bash-Komandos reinschreibst, und dann ein einer for-Schleife deinen Vergleich machen, das wäre viel kürzer 😉 und du müsstest, wenn du ein neues Komando hinzufügen willst, es einfach nur zur Liste hinzutun 😀
In der For-Schleife könntest du dann einfach einen Boolean auf true setzten oder so, wenn ein Wert erfolgreich verglichen wurde, und danach dann eine Prüfung mit dem Boolean machen, der die Fehlerausgabe regelt.
 
Der Objektorientierte Ansatz wäre hier evtl. eine Klasse oder Interface Command zu bauen. Da wäre dann sowas wie String getName() oder aber auch execute(String[] args) enthalten.

Dann hat man eine Liste von Klassen mit Commands. Diese geht man dann beim Start einmalig durch und
- schaut nach dem default Konstruktor und erstellt eine Instanz.
- legt dann eine HashMap an, in der halt Name und Instanz abgelegt werden.

Dann kann man nach einem Kommando ganz einfach schauen:
Command command = knownCommands.get(kommando);

Und dann kann man auch die Funktionalität direkt abbilden: command.execute(arguments);

So wird der Code gleich schön auf mehrere Klassen aufgeteilt.
 
Dann hat man eine Liste von Klassen mit Commands. Diese geht man dann beim Start einmalig durch und
- schaut nach dem default Konstruktor und erstellt eine Instanz.
- legt dann eine HashMap an, in der halt Name und Instanz abgelegt werden.

Erstellt man die speziellen Commands dann durch Reflection, bzw. wo bekommt man die Liste her?
Gibt es dann sowas wie MkdirCommand TouchCommand usw.?
 
Also einmalig muss man Reflection anwenden, um den Konstruktor zu bekommen. Danach hat man die Instanzen und kann das Interface nutzen.

Was gegen dieses Model spricht sind die Instanzen der Klassen. Die sind etwas unschön in meinen Augen und das wäre ein Grund, das Model noch etwas weiter aufzubohren.

So wäre ein Factory Pattern noch sinnvoll. Statt also die Kommandos aufzulisten, listet man dann nur noch Factories auf. Diese können dann Dinge wie:
- eine Liste der bekannten Befehle bringen. (In der Hash-Table hat man dann Befehl hin zu einer Instanz eines Interfaces mit createCommand(...) => Argumente habe ich jetzt nicht im Kopf. Weiter unten mehr.
- dann bei Bedarf die Commands erstellen. Das kann direkt im Listener sein oder über Anonyme Klassen / Lambdas.

So Commands werden etwas komplexer. So braucht ein Command:
- Argumente
- Eingabe-Stream
- Ein Ausgabe-Stream für die Ausgabe ist wichtig.
- Verschachtelte Commands!

Die Ein- und Ausgabestreams können reine Properties sein. Aber es wird schon recht komplex.

ls | more wäre dann eine Struktur, bei der ich von Hinten nach Vorne vorgehen würde:
more Befehl wird erzeugt, Tastatur-Eingabe bekommt dieses Command und die Ausgabe bekommen wir.
Dann wird ein ls Befehl erzeugt und der bekommt dann den more Befehl mit übergeben:
- ls bekommt keine Tastatureingabe und die Ausgabe bekommen nicht wir.
- ls gibt die Ausgabe an more weiter. (more hat damit zwei Eingaben - einmal die Tastur und einmal vom more Befehl!)
- Wenn ls gestartet wird, wird auch more gestartet!

Und das Interface wäre dann halt ein CommandCreator. In der Factory könnte da entweder die Factory selbst angegeben werden (Damit das Design möglich ist, ist der Befehl selbst auch ein Argument!) und dann wird da wieder ein if / switch statement benötigt.) oder das wird dann aufgebaut mit anonymen Klassen und im Konstruktor der Factory wird dann die Liste aufgebaut mit Code wie
Code:
..... = new CommandCreator() { // Analog dem ActionListener - da sieht es ja ähnlich aus ...
  public Command createCommand(String command, String[] args, Command parent) {
    // Some code
  }
}

Das kann man immer weiter ausbauen. Das ist jetzt auch nur eine Gedankenspielerei. Das ist also sehr grob wie es evtl. aussehen könnte.
 
Hallo,

Java:
.
.
.
String kommando = textEingeben("");  
        String[] teilen = kommando.split(" ");
        String argument = "argument";
.
.
.

ich versuche den eingelesenen String zu splitten und danach auszugeben. Nur will es nicht so wie ich es mir vostelle.

Java:
.
.
.
    case "ls":       System.out.println("command: '" + teilen[0] + "' with " + argument + " arguments (s)");break;
.
.
.

also teilen[0] soll den ersten wert ausgeben, indem fall "ls". Er gibt mir aber die komplette Zeile aus.
Mache ich bei der Split Methode was falsch oder bei der Ausgabe?

OK, es hat mit dem ....case "ls".... zu tun. Kann ich bei der "case" anweisung eine überprüfung einbauen wie
Java:
case teilen[0] == "ls":       System.out.println("command: '" + teilen[0] + "' with " + argument + " arguments (s)");break;
?
 
Zuletzt bearbeitet:
Wenn Du in kommando den ganzen Befehl hast und du das in das array teilen[] aufgeteilt hast, dann willst Du evtl. etwas wie folgt machen:
Code:
switch (teilen[0]) {
  case "ls":  // Code für ls
...
}

Also im case darf nur ein Wert stehen. Ein teilen[0]=="ls" ist da nicht zulässig. Zumal bei Strings ja auch nicht mit == sondern mit equals verglichen werden soll.

Hat Dir das weiter geholfen? Denn leider habe ich nicht alles voll verstanden, so dass ich evtl. für Dich wichtige Punkte nicht verstanden habe. Ggf. postest Du einmal den ganzen Code zum drüberschauen?
 
Vielen lieben dank für die Hilfe. Habe den Fehler jetzt gefunden.
ich hatte als switch folgendes stehen:

Java:
switch (kommando)  {
      
             case "ls":        System.out.println("command: '" + teilen[0] + "' with " + argument + " arguments (s)");break;

nachdem ich es auf

Java:
switch (teilen[0])  {
      
             case "ls":        System.out.println("command: '" + teilen[0] + "' with " + argument + " arguments (s)");break;

geändert habe funktioniert es auch wie ich es mir vorgestellt habe. 😀

Wie kann ich eigentlich die restlichen "argumente" zählen? Also ich meine alles wörter ausser teilen[0]?
 
Moin,

Java:
.
String kommando = textEingeben(""); 
        String[] teilen = kommando.split(" ");
        String argument = "argument";
ich versuche den eingelesenen String zu splitten und danach auszugeben. Nur will es nicht so wie ich es mir vostelle.
oder klappt das Splitten schon nicht ?? 🙄
Was genau steht in "kommando" drin ?

Gruß Klaus
 
So jetzt hat es geklappt. Auch das Zählen der Argumente mit einer for schleife. Nur er zählt alle wörter.
Wie kann ich alle wörter zählen ausser teilen[0]?

Kann ich nicht gleich bei der Ausgabe den Wert auf -1 setzen? Also eins runterzählen?

Java:
    case "ls":     System.out.println("command: '" + teilen[0] + "' with " + teilen.length + " arguments (s)");break;
 
Zuletzt bearbeitet:
Java:
   case "ls":     System.out.println("command: '" + teilen[0] + "' with " + (teilen.length - 1) + " arguments (s)");break;

in klammern setzen bringt Wunder mit sich. 😀
 

Zurück
Oben