Synopsis: How do I scanf, readln, etc. in Java? http://www.cafeaulait.org/javafaq.html
Klasse Passwort -zwei Listen Name und Passwort
Zwei Felder für Namen und Passwörter sind vorgegeben.
Erstellen Sie eine Methode ausgeben() , die alle Namen nebst Passwörtern auf der Konsole ausgibt.
0. Anna f1c4e
1. Bert 123gaga
2. Kalleman babe
Erstellen Sie eine Methode ausgeben2() , die alle Namen nebst Passwörtern formatiert auf der Konsole ausgibt.
Die Namen sollen 10 Zeichen breit dargestellt werden. Tipp: Mit Leerzeichen auffüllen.
1. Anna f1c4e
2. Bert 123gaga
3. Kalleman babe
Zeichen Sie ein Struktorgramm für ausgeben2().
Lösung
Entwickeln Sie die Methode check(n,p:Text):Boolean , mit Rückgabe true , wenn Name n und dazugehöriges Passwort p in den Feldern vorhanden ist, sonst Rückgabe false .
Entwickeln Sie die Methode aenderePswd(n,ap.np:Text):Boolean , zum Ändern des Passworts, dabei ist n der Name und ap,np altes und neues Passwort. Rückgabe true bei Erfolg, false sonst.
Lösung anzeigen..
Quellcode [Passwortprojekt/Passwort.java ]public class Passwort{
static String namen[ ] = { "Anna" ,"Bert" ,"Kalle" } ;
static String pswd[ ] = { "f1c4e" ,"123gaga" ,"babe" } ;
static void ausgeben( ) {
int i;
for ( i= 0 ; i< namen.length ; i++ ) {
System .out .print ( i+ ". " + namen[ i] + " " ) ;
System .out .println ( pswd[ i] ) ;
}
}
static void ausgeben2( ) {
int i,k;
for ( i= 0 ; i< namen.length ; i++ ) {
System .out .print ( i+ 1 + ". " + namen[ i] ) ;
for ( k= namen[ i] .length ( ) ; k<= 10 ; k++ )
System .out .print ( ' ' ) ;
System .out .println ( pswd[ i] ) ;
}
}
static boolean check( String n, String p) {
int i;
for ( i= 0 ; i< namen.length ; i++ )
if ( namen[ i] == n && pswd[ i] == p)
return true ;
return false ;
}
static boolean aenderePswd( String n,String ap,String np) {
int i;
for ( i= 0 ; i< namen.length ; i++ )
if ( namen[ i] == n && pswd[ i] == ap) {
pswd[ i] = np;
return true ;
}
return false ;
}
static void ausgebenPrintf( ) {
int i;
for ( i= 0 ; i< namen.length ; i++ ) {
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,namen[ i] ,pswd[ i] ) ;
}
}
}
Quellcode [Passwortprojekt/PasswortAufgaben.java ] public class PasswortAufgaben{
static String namen[ ] = { "Anna" ,"Bert" ,"Kalle" } ;
static String pswd[ ] = { "f1c4e" ,"123gaga" ,"babe" } ;
static void ausgeben( ) {
int i;
// Aufgabe
}
static void ausgeben2( ) {
int i,k;
// Aufgabe
}
static boolean check( String n, String p) {
int i;
// Aufgabe
return false ;
}
static boolean aenderePswd( String n,String ap,String np) {
int i;
// Aufgabe
return false ;
}
static void ausgebenPrintf( ) {
int i;
for ( i= 0 ; i< namen.length ; i++ ) {
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,namen[ i] ,pswd[ i] ) ;
}
}
}
Formatiertes Ausgeben mit printf
In praktisch jeder Programmierumgebung gibt es Funktionen um Ausgaben zu formatieren. Hier soll die Java-Methode printf vorgestellt werden.
1. Anna f1c4e
2. Bert 123gaga
3. Kalleman babe
public static void ausgebenPrintf(){
int i;
for(i=0;i<namen.length;i++){
System.out.printf("%2d. %-10s %s %n",i+1,namen[i],pswd[i]);
}
}
Format-Spezifizierer
Wirkung
%2d
Ausgabe zweistellige Dezimalzahl, rechtsbündig
%-10s
Ausgabe als String 10 Zeichen Platz durch - linksbündig
%s
Ausgabe String ohne besondere Formatierung
%n
Ausgabe neue Zeile-Zeichen
Speichern der Daten in einer Datei
Daten in Dateien (Files) zu speichern folgt diesem Prinzip:
Path pfad= Paths.get(dateipfad); // Pfad als String
Writer aus= Files.newBufferedWriter(pfad); // Datenstrom
aus.write("Daten schreiben"); // in den Strom schreiben
aus.close(); // schliessen, Gepuffertes wegschreiben
Es können dabei Probleme auftreten -Dateipfad existiert nicht, Datei ist schon durch anderes Programm geöffnet usw.
Exceptions (Ausnahmefehler)
In modernen Programmiersystemen werden Probleme in aufgerufenen Methoden durch Ausnahmefehlermeldungen (Exceptions) an die darüber liegenden Programmebenen gemeldet und dort bearbeitet.
In Java wird hierzu das try-catch-Konstrukt verwendet.
Java ist auch eine Insel / Ausnahmen müssen sein
Quellcode [Passwortprojekt/PasswortDateiWrite.java ] import java.io.* ; // Writer_Klasse
import java.nio.file.* ; // Pfad-Klasse
public class PasswortDateiWrite{
static String namen[ ] = { "Anna" ,"Bert" ,"Kalle" } ;
static String pswd[ ] = { "f1c4e" ,"123gaga" ,"babe" } ;
static String dateiname = "accounts.txt" ;
static void ausgebenDatei( ) {
int i;
Path pfad = Paths.get ( dateiname) ; // Dateipfad
try { // versuchen wir mal folgenden Code aus zu fuehren
Writer aus = Files.newBufferedWriter ( pfad) ; //Datenschreiber
for ( i= 0 ; i< namen.length ; i++ ) {
aus.write ( namen[ i] + "\t " + pswd[ i] + "\n " ) ; //schreibe
}
aus.close ( ) ; // schliesse Datenstrom
} catch ( IOException e) { //falls ein IO-Ausnahmefehler
System .out .println ( "IOException: " + e) ; //Fehler ausgeben
}
}
}
Implementieren Sie den Quelltext und testen Sie die Methode ausgebenDatei() .
Die ausgegebene Textdatei befindet sich im Projektordner.
Name und Passwort werden bei der Ausgabe durch ein Tabulatorzeichen "\t" getrennt.
Wenn aus.close(); weggelassen (auskommentiert) wird werden die Ausgaben ggfs. nicht abgespeichert, erst durch close() wird der Pufferspeicher im Hauptspeicher auf das Dateisystem weggeschrieben, testen Sie das.
Struktogramm mit try-catch
Ein Strukogramm zu erstellen gestaltet sich schwierig, da try-catch-Blöcke unbekannt waren als Strukogramme entwickelt wurden. Structorizer erlaubt trotzdem eine Darstellung.
String.format(..)
Formatiertes Ausgeben ist auch bei Dateien möglich: JavaInsel
aus.write(String.format("%2d. %-10s %s %n",i+1,namen[i],pswd[i]));
Erstellen Sie eine Methode ausgebenTabelle(filename:Text) für die formatierte Ausgabe einer Tabelle Nettopreis und Bruttopreis mit 19% Steuer, von 1€ bis 9€ in eine Datei filename ausgibt.
Erstellen Sie eine Methode ausgebenQuadrate(n:GZ) , die Quadratzahlen von 1 bis n formatiert in eine Datei quadrate.txt ausgibt.
Link zur Vertiefung
Java ist auch eine Insel: 18 Einführung in Dateien und Datenströme
Datei auslesen
Auch beim Lesen wird zunächst ein Datenstrom geöffnet. Es können einzelne Informationen oder auch ganze Zeilen gelesen werden.
Am Ende der Datei (End Of File - EOF) gibt die readLine() Methode einen null - Verweis zurück.
Dateizeilen einlesen und ausgeben bringt die Information nicht in die Arrays zurück...
Quellcode [Passwortprojekt/PasswortDateiRead.java ] import java.io.* ; // Writer_Klasse
import java.nio.file.* ; // Pfad-Klasse
public class PasswortDateiRead{
static String dateiname = "accounts.txt" ;
static void leseDatei( ) {
String zeile;
Path pfad = Paths.get ( dateiname) ; // Dateipfad
try { // versuchen wir mal folgenden Code aus zu fuehren
BufferedReader ein = Files.newBufferedReader ( pfad) ; // oeffne Datenstrom
while ( ( zeile = ein.readLine ( ) ) != null ) { // solange Datensaetze vorhanden, lese Zeile
System .out .println ( zeile) ; // gib Zeile aus
}
ein.close ( ) ; // schliesse Datenstrom
} catch ( IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System .out .println ( "IOException: " + e) ; // gib den Fehler auf der Konsole aus
}
}
}
Lesen von name und pswd aus Datei
Die Namen und Passwörter sollen wieder in die Arrays eingelesen werden.
Zunächst werden jeweils 5 Strings vorgesehen.
ausgebenPrintf() gibt null bei leeren Strings aus, unterbinden Sie das.
Die aus der Datei eingelesene Zeile soll beim Tabulator zerteilt werden.
Ergänzen Sie lesePasswortDatei() entsprechend.
Lösung anzeigen..
Quellcode [Passwortprojekt/PasswortDateiRead2.java ]import java.io.* ; // Writer_Klasse
import java.nio.file.* ; // Pfad-Klasse
public class PasswortDateiRead2{
static String dateiname = "accounts.txt" ;
static String namen[ ] = new String [ 5 ] ; // Array fuer 5 Strings
static String pswd[ ] = new String [ 5 ] ;
static void lesePasswortDatei( ) {
int datensatz = 0 ; // zaehlt die gelesenen Datensaetze
int i;
char c;
String zeile;
Path pfad = Paths.get ( dateiname) ; // Dateipfad
try { // versuchen wir mal folgenden Code aus zu fuehren
BufferedReader ein = Files.newBufferedReader ( pfad) ; // oeffne Datenstrom
while ( ( zeile = ein.readLine ( ) ) != null ) { // solange Datensaetze vorhanden, lese Zeile
namen[ datensatz] = "" ;
pswd[ datensatz] = "" ;
for ( i= 0 ; i< zeile.length ( ) ; i++ ) { // die Zeile bis Tab durchgehen
c= zeile.charAt ( i) ;
if ( c!= '\t ' ) { // wenn es kein Tabulator ist
namen[ datensatz] += c;
}
else {
i++; // Tabulator ueberspringen
break ;
}
}
for ( ; i< zeile.length ( ) ; i++ ) { // bis zum Ende
pswd[ datensatz] += zeile.charAt ( i) ;
}
datensatz++;
}
ein.close ( ) ; // schliesse Datenstrom
} catch ( IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System .out .println ( "IOException: " + e) ; // gib den Fehler auf der Konsole aus
}
}
static void ausgebenPrintf( ) {
int i;
for ( i= 0 ; i< namen.length ; i++ ) {
if ( namen[ i] == null ) break ;
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,namen[ i] ,pswd[ i] ) ;
}
}
} Erstellen Sie ein Struktogramm für lesePasswortDatei().
Sind mehr als 5 Datensätze in der Datei wird eine Exception ausgegeben, wie kann das verhindert werden?
Fragen:
Was ist eine Exception?
Wozu ist try-catch nötig?
Warum ist die Anweisung import java.io.*; notwendig?
Welche Schritte sind für Dateiausgabe notwendig?
Warum müssen Dateien wieder geschlossen werden?
Quellcode [Passwortprojekt/PasswortDateiRead2Aufgabe.java ] import java.io.* ; // Writer_Klasse
import java.nio.file.* ; // Pfad-Klasse
public class PasswortDateiRead2Aufgabe{
static String dateiname = "accounts.txt" ;
static String namen[ ] = new String [ 5 ] ; // Array fuer 5 Strings
static String pswd[ ] = new String [ 5 ] ;
static void lesePasswortDatei( ) {
int datensatz = 0 ; // zaehlt die gelesenen Datensaetze
int i;
char c;
String zeile;
Path pfad = Paths.get ( dateiname) ; // Dateipfad
try { // versuchen wir mal folgenden Code aus zu fuehren
BufferedReader ein = Files.newBufferedReader ( pfad) ; // oeffne Datenstrom
while ( ( zeile = ein.readLine ( ) ) != null ) { // solange Datensaetze vorhanden, lese Zeile
namen[ datensatz] = "" ;
pswd[ datensatz] = "" ;
for ( i= 0 ; i< zeile.length ( ) ; i++ ) { // die Zeile bis Tab durchgehen
c= zeile.charAt ( i) ;
// Aufgabe: namen einlesen
}
for ( ; i< zeile.length ( ) ; i++ ) { // bis zum Ende
pswd[ datensatz] += zeile.charAt ( i) ;
}
datensatz++;
}
ein.close ( ) ; // schliesse Datenstrom
} catch ( IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System .out .println ( "IOException: " + e) ; // gib den Fehler auf der Konsole aus
}
}
static void ausgebenPrintf( ) {
int i;
for ( i= 0 ; i< namen.length ; i++ ) {
// Aufgabe: Bei null aufhoeren
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,namen[ i] ,pswd[ i] ) ;
}
}
}
Datensatzanzahl und split-Funktion
Anzahl der zu lesenen Datensätze kennen
write(..) kann auch Werte schreiben: Anzahl der Datensätze am Anfang der Datei schreiben und beim Einlesen entsprechend viele Plätze reservieren.
Eingelesene Datei-Zeilen leichter verarbeiten.
Eingelesenen String mit split(..) zerlegen.
JavaInsel
Wikipedia: Reguläre Ausdrücke
Quellcode [Passwortprojekt/PasswortSplit.java ] import java.io.* ;
import java.nio.file.* ; // Pfad-Klasse
public class PasswortSplit{
static String namen[ ] = { "Anna" ,"Bert" ,"Kalle" } ;
static String pswd[ ] = { "f1c4e" ,"123gaga" ,"babe" } ;
static String dateiname = "accounts.txt" ;
public static void ausgebenDatei( ) {
int i;
try { // versuchen wir mal folgenden Code aus zu fuehren
Writer aus = Files.newBufferedWriter ( Paths.get ( dateiname) ) ;
aus.write ( namen.length ) ; // Anzahl der Daten speichern
for ( i= 0 ; i< namen.length ; i++ ) {
aus.write ( namen[ i] + "\t " + pswd[ i] + "\n " ) ; //schreibe mit Tabulator getrennt
}
aus.close ( ) ; // schliesse Datenstrom
} catch ( IOException e) { // falls ein IO-Ausnahmefehler auftritt
System .out .println ( "IOException: " + e) ; // gib den Fehler aus
}
}
public static void leseDaten( ) {
int anzahl,i= 0 ;
String zeile;
String [ ] teile;
try {
BufferedReader ein = Files.newBufferedReader ( Paths.get ( dateiname) ) ;
anzahl = ein.read ( ) ; // lese Anzahl der Datensaetze
System .out .println ( "Anzahl Datensaetze: " + anzahl) ;
namen = new String [ anzahl] ; // erzeuge entsprechende Speicherplaetze
pswd = new String [ anzahl] ;
while ( ( zeile = ein.readLine ( ) ) != null ) {
teile = zeile.split ( "\t " ) ; // zerteile Zeile
namen[ i] = teile[ 0 ] ;
pswd[ i] = teile[ 1 ] ;
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,namen[ i] ,pswd[ i] ) ;
i++;
}
ein.close ( ) ;
} catch ( IOException e) {
System .out .println ( "IOException: " + e) ;
}
}
}
ArrayList
Beliebig viele Strings ohne viel Aufwand anhängen.
Array-List:JavaInsel
Quellcode [Passwortprojekt/PasswortList.java ] import java.io.* ;
import java.nio.file.* ;
import java.util.* ; // List
public class PasswortList{
static List< String> namen = new ArrayList<> ( ) ;
static List< String> pswd = new ArrayList<> ( ) ;
static String dateiname = "accounts.txt" ;
static void test( ) { // Einfuegen zeigen
namen.addAll ( Arrays .asList ( "Anna" ,"Bert" ,"Kalle" ) ) ;
pswd.addAll ( Arrays .asList ( "f1c4e" ,"123gaga" ,"babe" ) ) ;
}
public static void leseDaten( ) {
String zeile;
String [ ] teile;
try {
BufferedReader ein = Files.newBufferedReader ( Paths.get ( dateiname) ) ;
while ( ( zeile = ein.readLine ( ) ) != null ) {
teile = zeile.split ( "\t " ) ; // zerteile Zeile
namen.add ( teile[ 0 ] ) ;
pswd.add ( teile[ 1 ] ) ;
}
ein.close ( ) ;
} catch ( IOException e) {
System .out .println ( "IOException: " + e) ;
}
}
static void ausgeben( ) {
int i;
for ( i= 0 ; i< namen.size ( ) ; i++ ) {
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,namen.get ( i) ,pswd.get ( i) ) ;
}
}
}
Eine Liste mit Account-Objekten
Zwei getrennte Listen für Namen und Passwörter sind nicht praktisch.
Die Datensätze werden jetzt in Account-Objekten gespeichert. Eine Klasse Account gibt die Datenstruktur vor.
In einer Klasse Passwortverwalter werden die Account-Objekte als Liste verwaltet.
Mit der Operation test() können Beispieldatensätze angelegt werden.
Praktische Info:
TG-Formelsammlung
Quellcode [PasswortOOP/PasswortVerwalterAufg.java ] import java.io.* ;
import java.nio.file.* ;
import java.util.* ; // List
public class PasswortVerwalterAufg{
static List< Account> accounts = new ArrayList< Account> ( ) ;
static String dateiname = "accounts.txt" ;
static void test( ) {
accounts.add ( new Account( "Anna" ,"f1c4e" ) ) ;
accounts.add ( new Account( "Bert" ,"123gaga" ) ) ;
accounts.add ( new Account( "Kalle" ,"babe" ) ) ;
}
static void ausgeben( ) {
int i;
for ( i= 0 ; i< accounts.size ( ) ; i++ ) {
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,accounts.get ( i) .name ,
accounts.get ( i) .pswd ) ;
}
}
static void leseDaten( ) {
String zeile;
String [ ] teile;
try {
BufferedReader ein = Files.newBufferedReader ( Paths.get ( dateiname) ) ;
while ( ( zeile = ein.readLine ( ) ) != null ) {
teile = zeile.split ( "\t " ) ; // zerteile Zeile
accounts.add ( new Account( teile[ 0 ] ,teile[ 1 ] ) ) ;
}
ein.close ( ) ;
} catch ( IOException e) {
System .out .println ( "IOException: " + e) ;
}
}
static boolean check( String n, String p) {
int i;
// Aufgabe
return false ;
}
static boolean neuerAccount( String n,String p) {
int i;
// Aufgabe
return true ;
}
static void ausgebenDatei( ) {
int i;
try { // versuchen wir mal folgenden Code aus zu fuehren
// Aufgabe
} catch ( IOException e) { // falls ein IO-Ausnahmefehler auftritt
System .out .println ( "IOException: " + e) ; // gib den Fehler aus
}
}
}
Quellcode [PasswortOOP/Account.java ]public class Account{
String name;
String pswd;
Account( String n,String p) { //Konstruktor
name = n;
pswd = p;
}
} Testdaten [PasswortOOP/accounts.txt ]Nino 38zHHei8*
Robert hGe3Uiie9
Marie nez7wwiI Aufgaben
Eine Operation check(n:Text,p:Text):bool überprüft, ob bei existierenden Namen n das Passwort p stimmt.
Eine Operation neuerAccount(n:Text,p:Text):bool überprüft, ob der Name schon existiert, sonst wird ein neues Account-Objekt erzeugt und in die Liste hinzugefügt.
ausgebenDatei() gibt die Account-Liste in eine Datei aus.
Lösung anzeigen..
Quellcode [PasswortOOP/PasswortVerwalter.java ]import java.io.* ;
import java.nio.file.* ;
import java.util.* ; // List
public class PasswortVerwalter{
static List< Account> accounts = new ArrayList< Account> ( ) ;
static String dateiname = "accounts.txt" ;
static void test( ) {
accounts.add ( new Account( "Anna" ,"f1c4e" ) ) ;
accounts.add ( new Account( "Bert" ,"123gaga" ) ) ;
accounts.add ( new Account( "Kalle" ,"babe" ) ) ;
}
static void ausgeben( ) {
int i;
for ( i= 0 ; i< accounts.size ( ) ; i++ ) {
System .out .printf ( "%2d. %-10s %s %n" ,i+ 1 ,accounts.get ( i) .name ,
accounts.get ( i) .pswd ) ;
}
}
static void leseDaten( ) {
String zeile;
String [ ] teile;
try {
BufferedReader ein = Files.newBufferedReader ( Paths.get ( dateiname) ) ;
while ( ( zeile = ein.readLine ( ) ) != null ) {
teile = zeile.split ( "\t " ) ; // zerteile Zeile
accounts.add ( new Account( teile[ 0 ] ,teile[ 1 ] ) ) ;
}
ein.close ( ) ;
} catch ( IOException e) {
System .out .println ( "IOException: " + e) ;
}
}
static boolean check( String n, String p) {
int i;
for ( i= 0 ; i< accounts.size ( ) ; i++ )
if ( accounts.get ( i) .name == n && accounts.get ( i) .pswd == p)
return true ;
return false ;
}
static boolean neuerAccount( String n,String p) {
int i;
for ( i= 0 ; i< accounts.size ( ) ; i++ ) {
if ( accounts.get ( i) .name == n)
return false ; // name gibt es schon
}
accounts.add ( new Account( n,p) ) ; // neues Objekt erzeugen
return true ;
}
static void ausgebenDatei( ) {
int i;
try { // versuchen wir mal folgenden Code aus zu fuehren
Writer aus = Files.newBufferedWriter ( Paths.get ( dateiname) ) ;
for ( i= 0 ; i< accounts.size ( ) ; i++ ) {
aus.write ( accounts.get ( i) .name + "\t " + accounts.get ( i) .pswd + "\n " ) ;
}
aus.close ( ) ; // schliesse Datenstrom
} catch ( IOException e) { // falls ein IO-Ausnahmefehler auftritt
System .out .println ( "IOException: " + e) ; // gib den Fehler aus
}
}
}
Ausblick, ToDo
Passwörter verschlüsselt speichern (Hashwerte)
Eingaben und Konsistenzen besser überprüfen
Passwortregeln einführen und überprüfen
Erweitern um Nickname, Ausgabe, Dateischreiben und Lesen in Account-Klasse verlagern
Polymorphie demonstrieren
Als XML-Format speichern