Wie nutze ich InputStream?

Anfaengerin

Aktives Mitglied
Hallo, wie nutze ich Inputstream am Besten in Kombination mit der Methode available? Ich will ein Zeichen einlesen lassen. Muss ich wie bei der Klasse Scanner Inputstream erst importieren? Wie ist die Syntax?
 
Generell musst Du keine Klassen importieren. Du kannst das Importieren als eine Art Verzeichnis ansehen, das dafür sorgt, dass Du den vollen Namen des Klasse (inkl. Package) nicht angeben musst.

Also wie ein Adressbuch. Du brauchst keinen Eintrag im Adressbuch um mit einem Routenplaner eine Route zu berechnen. Nur dann musst Du halt dem Routenplaner die ganze Adresse geben. Mit einem Eintrag reicht es, dem Routenplaner zu sagen, dass Du zu dem Adressbucheintrag möchtest.

Konkret für InputStream bedeutet dies:

Du kannst den InputStream importieren und dann direkt auf InputStream zugreifen:
Java:
import java.io.InputStream;

public class MyClass {
    private InputStream myStream;
}

==> Du hast einen import auf java.io.InputStream und daher kannst Du den InputStream direkt nutzen.

Java:
public class MyClass {
    private java.io.InputStreammyStream;
}

==> Du hast keinen import, daher musst Du bei Klassen den vollen Namen angeben incl. Package.

Dann ist wichtig: Wenn Du etwas zu Klassen des Java Frameworks wissen willst: Schau Dir die Dokumentation an. Diese findest Du z.B. unter:

Um so einen Link zu finden kannst Du auf die Startseite der JavaDoc Dokumentation gehen:
Oben Rechts ist ein Suchfeld - da einfach eingeben: InputStream und schon findest Du die Anleitung.

Hier kannst Du dann einzelne Bytes einlesen. Wichtig ist: InputStream kennt nur einzelne Bytes. Die Bedeutung dieser Bytes (also "Zeichen") ist einem InputStream nicht bekannt. Hier müsstest Du entweder die Bedeutung selbst geben oder Du müsstest eine Klasse verwenden, die dies für Dich macht. Dabei ist wichtig: Es gibt eine feste Zuweisung. Es gibt viele unterschiedliche mögliche Umwandlungen ("Encodings").

Evtl. reicht es einfach für Deine Belange, dass Du hier auf sogenannte ASCII Zeichen prüfst. Dies ist ein Encoding, welches für einige übliche Encodings übereinstimmt und die auch über den Datentyp char in Java verwendet werden kann. So kannst Du z.B. einfach ein byte einlesen und den Wert in ein char umwandeln um dann das char anzuzeigen. Also ohne InputStream wäre das dann z.B. sowas:

Java:
        byte b = 65; // 'A'
        char c = (char) b;
        System.out.println(c);

Das ist aber nicht ganz korrekt, was Du merken wirst, wenn Du Sonderzeichen verwendest.

Wenn Du Klassen haben willst, die direkt Zeichen und Strings kennen, dann wären das die Reader. So kannst Du z.B. ein InputStreamReader auf einem InputStream verwenden, um dann Zeichen lesen zu können.

Falls Du auf System.in arbeiten willst, wäre hier noch der Hinweis wichtig: Durch die verwendung von InputStream Methoden verändert sich nichts am typischen Verhalten der Konsole in Java. Auch wenn Du da einzelne Bytes lesen kannst, werden diese erst nach einem Druck auf Return / Enter bereitgestellt.
 
Eine typische Anwendung ist die Prüfung, ob Daten bereit stehen zum Einlesen um nur dann ein Einlesen zu starten, wenn Daten bereit stehen. Das verhindert ein Blockieren eines Threads.

Wenn man die Dokumentation der Methode liest, dann findet sich noch der Hinweis, dass es generell als falsch angesehen wird, wenn die Methode zur Bestimmung einer Puffergröße verwendet wird. (Das ist ein typisches Pattern, das ich vor allem aus der C / C++ Welt kenne. Da wird dann erst geprüft: "Wie viel Platz brauche ich?", dann wird der benötigte Platz gefüllt und dann findet der Aufruf zum Füllen des reservierten Platzes statt.)

An der Stelle dann aber noch der Hinweis auf java.nio.* - wenn das Ziel ist, dass Aufrufe nicht blockieren, dann sind ggf. unter dem Package java.nio besser geeignete Klassen zu finden. Das aber nur als kleine Randbedingung.
 
Auch einmal ein konkretes Beispiel:

Java:
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException, InterruptedException {
        // Aufruf etwas zu lesen ohne Check -> Blockiert die Ausführung
        System.out.println("Bitte etwas eingeben ...");
        int input = System.in.read();
        char c = (char) input;
        System.out.println("Erstes Zeichen: Wert: " + input + ", Zeichen: " + c);

        // Hier geht es erst nach der Eingabe weiter und es wird alles gelesen ...
        while (System.in.available() > 0) {
            input = System.in.read();
            c = (char) input;
            System.out.println("weiteres Zeichen: Wert: " + input + ", Zeichen: " + c);
        }

        System.out.println("Alles gelesen ...");

        // Prüfen auf die Eingabe ...
        while (System.in.available() == 0) {
            System.out.print(".");
            Thread.sleep(500);
        }
        while (System.in.available() > 0) {
            input = System.in.read();
            c = (char) input;
            System.out.println("weiteres Zeichen: Wert: " + input + ", Zeichen: " + c);
        }
    }
}

Du siehst erst einmal bei der Ausführung: Er kommt zu dem ersten read() und hält dann an. Das Programm wartet, bis Du etwas eingegeben hast und die Enter/Return Taste gedrückt hast. Dann wird direkt das gelesene Zeichen ausgegeben. Dazu verwenden wir dann das einfache Umwandeln in einen char und man erkennt da den eigentlichen Wert und das Zeichen. (Habe ich beides ausgegeben).

Dann wird in einer Schleife geprüft, ob noch Zeichen vorhanden sind. Diese werden direkt gelesen. Da sollte dir dann auffallen: Das Return / Enter ist auch ein Zeichen (oder gar eine Zeichenkombination) und wird dann auch angezeigt. Dann kommt das "Alles gelesen ..."

Dann bleibt das Programm aktiv während es ständig prüft, ob eine Eingabe vorliegt. Um das deutlich zu machen, habe ich einfach einen "." ausgegeben. Und eine kurze Pause von einer halben Sekunde damit Du den Überblick hast.

Wenn dann eine Eingabe gemacht wurde, wird diese auch wieder komplett gelesen und das Programm beendet sich ohne noch einmal zu blockieren.

Das wäre also eine mögliche Anwendung. Ein Programm kann irgendwas machen und zwischendrin kann immer geprüft werden: Hat der Benutzer etwas eingegeben?

Dazu reduzieren wir den Code einfach nur auf die Schleife, die die "." ausgibt:

Java:
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException, InterruptedException {
        while (System.in.available() == 0) {
            System.out.print(".");
            Thread.sleep(500);
        }
    }
}

Jetzt macht das Programm etwas und sobald Du die Enter Taste drückst, beendet es sich.
 
Danke...ich habe jetzt

Java:
package org.example;

import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws InterruptedException {

               String Strecke = "w";

        int consoleLength = 10110;

        for(int i=1; i < 20000; i++) {

        if(i % 10110 ==0)
        {
            System.out.println();

        }
        else

        {
            System.out.print(Strecke);

            Strecke = "\b " + Strecke;

            Thread.sleep(500);
        }
    }

Also ein kleiner Punkt "wandert" (erscheint und wird gelöscht) über die Konsole. Jetzt brauche ich einen "Scanner", der die While-Schleife nicht unterbricht und den Nutzer auffordert, ein Zeichen einzugeben. Dieses Zeichen wird dann erscheinen und wieder gelöscht werden statt des Punktes.
 
Ich hab jetzt:

Java:
package org.example;

import java.io.IOException;

import java.io.InputStream;

import java.io.BufferedReader;

import java.io.FileReader;

import java.io.IOException;

import java.io.*;


public class Probieren {
    public static void main(String[] args) throws Exception {


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


        String Strecke = ".";


        while (true) {
            System.out.print(Strecke);

            Strecke = "\b " + Strecke;

            Thread.sleep(500);

            if (System.in.available() > 0) {

                String k = br.readLine();
                if (k.equals(null)) {

                    Thread.sleep(500);
                    Strecke = ".";
                    Strecke = "\b " + ".";
                    System.out.print(Strecke);
                }

                else {
                    Thread.sleep(250);

                    System.out.println(k);
                    Strecke = "\b " + k;
                    System.out.print(Strecke);

                    Thread.sleep(500);
                }
            }


            Thread.sleep(250); //Während dieser Zeit kann auch nichts eingegeben werden also nicht zu hoch setzen
        }
    }

}

So macht er es, dass ich, wenn der Nutzer einfach Enter drückt ohne ein Zeichen einzugeben, der Punkt einfach weiterwandert. Aber wenn ich diesen Bereich erfolgreich habe

Code:
String k = br.readLine();
 if (k.equals(null)) {

                    Thread.sleep(500);
                    Strecke = ".";
                    Strecke = "\b " + ".";
                    System.out.print(Strecke);
                }

...dann funktioniert dieser nicht mehr richtig:

Code:
else {
                    Thread.sleep(250);

                    System.out.println(k);
                    Strecke = "\b " + k;
                    System.out.print(Strecke);

                    Thread.sleep(500);
                }
            }

Das heißt, er tauscht den Punkt, der wandert, nicht mehr in den eingegebenen Buchstaben um.
 

Zurück
Oben