Angewandte Netzwerktechnik kompakt

Material zum Buch

zu Kapitel 3.3 (my1stJSON)


Zu Kapitel 3.3 steht uns die Klasse my1stJSON zur Verfügung, die die Datei JSON-Beispiel.json einliest. Diese Datei muss in dem Verzeichnis liegen, in dem die .class-Datei des Programms liegt.

Zur Verwendung der Klasse my1stJSON wird die Bibliothek Gson verwendet, welche Daten aus der Java-Struktur heraus direkt in das JSON-Format umsetzen kann und umgekehrt. Die Bibliothek und alle benötigten Verweise sind bereits in Quellcode vorhanden. Weitere Informationen über die Bibliothek ist unter http://code.google.com/p/google-gson abrufbar. Abbildung 3.1 im Buch zeigt, wie die Bibliothek zu einem Eclipse-Projekt hinzugefügt werden kann.

Am Ende der Seite finden Sie eine Vorschau der Klasse.

zu Kapitel 3.4 (Studentenverwaltung)


In Kapitel 2 (Grundlagen) standen uns das Interface LesenSchreiben, sowie die Klassen TextIO, BinaerIO, Leistung, Student, Speicher und Verwaltung zur Verfügung, mit denen zufällig erzeugte Stundentendaten in eine Textdatei oder eine Binärdatei geschrieben werden können.

Für Kapitel 3.4 ist das Archiv um die Klasse JSON_IO erweitert, mit der die erzeugten Studentendaten nun auch als JSON-Datei abgespeichert werden können. Die Daten werden dabei, wie bei der Erzeugung einer Textdatei, in einen OutputStreamWriter, gekoppelt mit einem FileOutputStream, geschrieben. Der grundlegende Ablauf des Programms ist identisch.

Das entsprechende Ausgabeformat kann in der Klasse Verwaltung gewählt werden. Das verlinkte Archiv enthält zu jedem Ausgabeformat bereits je eine erzeugte Datei.

Zur Verwendung der Klasse JSON_IO wird die Bibliothek Gson benötigt, welche Daten aus der Java-Struktur heraus direkt in das JSON-Format umsetzen kann und umgekehrt. Die Bibliothek und alle benötigten Verweise sind bereits in Quellcode vorhanden. Weitere Informationen über die Bibliothek ist unter http://code.google.com/p/google-gson abrufbar. Abbildung 3.1 im Buch zeigt, wie die Bibliothek zu einem Eclipse-Projekt hinzugefügt werden kann.

Am Ende der Seite finden Sie eine Vorschau der Klassen.

Vorschau der Java-Klassen zu Kapitel 3.3


my1stJSON.java

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader; 
import java.io.Reader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class my1stJSON { 

	public class Student {

		public int matrikelNummer;
		public String name; 
		public Leistung[] leistungen;
		
		@Override
		public String toString() {
			String result = 
					matrikelNummer+"\t"+name;
			return result;
		}
	}

	public class Leistung {

		public String modul;
		public double note;	
		@Override
		public String toString() {
			String result = 
					modul+" - "+note;
			return result;
		}
	}

	public static void main(String[] args) throws IOException {

		try (
			FileInputStream FIS = new FileInputStream("JSON-Beispiel.json");
			Reader reader = new InputStreamReader(FIS, "UTF-8")) {
			Gson gson = new GsonBuilder().create();
			Student studenten[] = gson.fromJson(reader, Student[].class);

			for (int studentNr = 0; studentNr < studenten.length; studentNr++)
			{
				System.out.print(studenten[studentNr]+"\t");

				if (studenten[studentNr].leistungen != null)
				{
					for (int leistungNr = 0; leistungNr < studenten[studentNr].leistungen.length; leistungNr++)
						System.out.print(studenten[studentNr].leistungen[leistungNr]+" | ");
					System.out.println();
				}
				else System.out.println();
			}
		} 
	}
}

Vorschau der Java-Klassen zu Kapitel 3.4


BinaerIO.java

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BinaerIO implements LesenSchreiben {

	String dateiName;
	
	BinaerIO(String dateiName)
	{
		this.dateiName = dateiName;
	}
	
	@Override
	public void schreibeDatei(Student[] studenten) throws IOException {
		FileOutputStream fos = new FileOutputStream(dateiName);
		DataOutputStream dos = new DataOutputStream(fos);
		
		if(studenten != null) {
			dos.writeInt(studenten.length);
			for(int i=0; i < studenten.length; i++) {
				dos.writeInt(studenten[i].matrikelNummer);
				dos.writeUTF(studenten[i].name);
				if(studenten[i].leistungen != null) {
					dos.writeInt(studenten[i].leistungen.length);

					for(int j=0; j < studenten[i].leistungen.length; j++) {
						dos.writeUTF(studenten[i].leistungen[j].modul);
						dos.writeDouble(studenten[i].leistungen[j].note);
					}
				}
				else
					dos.writeInt(0);	
			}
		}
		else
			dos.writeInt(0);
		dos.close();
		fos.close();
	}

	@Override
	public Student[] leseDatei() throws IOException {
		Student[] geleseneStudenten;

		FileInputStream fis = new FileInputStream(dateiName);
		DataInputStream dis = new DataInputStream(fis);

		int studCnt = dis.readInt();
		if(studCnt != 0)
		{
			geleseneStudenten = new Student[studCnt];
			for(int i=0; i < studCnt; i++) {
				geleseneStudenten[i] = new Student();
				geleseneStudenten[i].matrikelNummer = dis.readInt();
				geleseneStudenten[i].name = dis.readUTF();
				int leistCnt = dis.readInt();

				if(leistCnt != 0) {
					geleseneStudenten[i].leistungen = new Leistung[leistCnt];
					for(int j=0; j < leistCnt; j++) {
						geleseneStudenten[i].leistungen[j] = new Leistung();
						geleseneStudenten[i].leistungen[j].modul = dis.readUTF();
						geleseneStudenten[i].leistungen[j].note = dis.readDouble();
					}
				}
				else
					geleseneStudenten[i].leistungen = null;	
			}

		}
		else
			geleseneStudenten = null;

		dis.close();
		fis.close();
		return geleseneStudenten;
	}
	

}

JSON_IO.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class JSON_IO implements LesenSchreiben {
	
	String dateiName;
	Gson gson;
	
	JSON_IO(String dateiName) {
		this.dateiName = dateiName;
		gson = new GsonBuilder().create();
	}
	
	@Override
	public void schreibeDatei(Student[] studenten) throws IOException {
		FileOutputStream fos = new FileOutputStream(dateiName);
		OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
		
		gson.toJson(studenten,osw);
		
		osw.close();
		fos.close();
	}

	@Override
	public Student[] leseDatei() throws IOException {
		Student[] geleseneStudenten;
		FileInputStream fis = new FileInputStream(dateiName);
		InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
		
		geleseneStudenten = gson.fromJson(isr,Student[].class);
		
		isr.close();
		fis.close();
		
		return geleseneStudenten;
	}
	
}

Leistung.java

public class Leistung {
	public String modul;
	public double note;
	
	// Huebsche Ausgabe als String
	@Override 
	public String toString() {
		return modul + " " + note;
	}
}

LesenSchreiben.java

import java.io.IOException;

// Interface, das das Lesen und Schreiben der Datensätze kapselt
// Dateinamen/Netzwerkadressen werden im Konstruktur der Klasse behandelt, 
// die instantiiert wird. 
public interface LesenSchreiben {
	void schreibeDatei(Student[] studenten) throws IOException;
    Student [] leseDatei() 	throws IOException;
}

Speicher.java

public class Speicher {
	// Array, das die Studenten speichert
	// Kniff: Der Inhalt des Speichers existiert nur einmal, da static
	private static final Student[] studenten;

	// Kniff: Der Inhalt des Speichers wird durch diese Methode beim ersten Zugriff erzeugt
	static
	{
		// Datensaetze erzeugen
		studenten = Speicher.fuelleMitUnsinn(100);
	}

	// Methoden fuer den Zugriff auf die gespeicherten Daten
	public static Student[] getStudenten()
	{
		return studenten;
	}

	public static Student getSucheMatrikelNummerZuName(String name)
	{
		for(Student s : studenten)
		{
			if(s.name.equals(name))
			{
				return s;
			}
		}
		return null;
	}

	public static Student getStudentenInfoZuMatrikelNummer(int matrikelNummer)
	{
		for(Student s : studenten)
		{
			if(s.matrikelNummer == matrikelNummer)
			{
				return s;
			}
		}	
		return null;
	}	

	// Utility-Methoden
	public static Student[] fuelleMitUnsinn(int Zahl)
	{
		// Hilfsvariablen zum Erzeugen von Datensaetzen
		  final String [] vornamen = { "Mia","Ben","Emma","Jonas","Hannah","Leon","Sofia","Finn","Anna","Elias"};
		  final String [] nachnamen = {"Bauer","Becker","Fischer","Fuchs","Hartmann","Lang", "Jung","Hofmann","Huber"};
		  final String [] module = {"Analysis A","Lineare Algebra A","Analysis B","Lineare Algebra B","Numerik A",
				"Stochastik A","Stochastik B","Numerik partieller Differentialgleichungen 1","Numerik partieller Differentialgleichungen 2",
				"Baumechanik I (Statik starrer Koerper)","Baumechanik II (Elastomechanik)","Baumechanik III (Kinematik und Kinetik)",
				"Kontinuumsmechanik I","Modellbildung im Ingenieurwesen","Numerische Mechanik","Festkoerpermechanik","Finite Elemente II",
				"Grundlagen der Elektrotechnik","Umweltbiologie und -chemie","Stroemungsmechanik","Thermodynamik im Ueberblick",
				"Datenstrukturen, Algorithmen und Programmierung","Datenbanksysteme im Ingenieurwesen","Graphen und Netze","Baustoffkunde I",
				"Baustoffkunde II","Ausgleichungsrechnung und Statistik I","Ausgleichungsrechnung und Statistik II",
		"Projekte des Ingenieurwesens" };

		Student[] unsinn = new Student[Zahl];

		for(int i=0; i < Zahl; i++) {
			unsinn[i]=new Student();
			int vn_indx = (int)(Math.random()*vornamen.length);
			int nn_indx = (int)(Math.random()*nachnamen.length);
			unsinn[i].name = vornamen[vn_indx] + " " + nachnamen[nn_indx];
			unsinn[i].matrikelNummer = vn_indx * 100 + nn_indx + i * 10000;
			int notenZahl = (int)(Math.random()*8);
			if(notenZahl >= 1) {
				unsinn[i].leistungen = new Leistung[notenZahl];
				for(int j=0; j < notenZahl; j++) {
					int mod_indx = (int)(Math.random()*module.length);
					unsinn[i].leistungen[j] = new Leistung();
					unsinn[i].leistungen[j].modul = module[mod_indx];
					unsinn[i].leistungen[j].note = (int)(Math.random()*5) + 1;
				}
			}
			else
				unsinn[i].leistungen = null;
		}
		return unsinn;
	}

	public static boolean sindArraysGleich(Student[] a, Student[] b) {
		boolean istUnGleich = false;
		if(a.length == b.length)
		{
			for(int i=0; i < a.length; i++) {
				istUnGleich |= a[i].matrikelNummer != b[i].matrikelNummer;
				istUnGleich |= !(a[i].name.equals(b[i].name));
				if(a[i].leistungen != null) {
					for(int j=0; j < a[i].leistungen.length; j++) {
						istUnGleich |= !(a[i].leistungen[j].modul.equals(b[i].leistungen[j].modul)) ;
						istUnGleich |= a[i].leistungen[j].note != b[i].leistungen[j].note ;
					}
				}
				if(istUnGleich)
					System.out.println("Ungleich a="+ a + "| b=" + b);
			}
		}
		else
			istUnGleich = true;

		return !istUnGleich;
	}
}

Student.java

public class Student {
	public int matrikelNummer;
	public String name;
	public Leistung[] leistungen;
	
	// Huebsche Ausgabe als String
	@Override 
	public String toString() {
		String ausgabe = matrikelNummer + " " + name + "\n";
		if(leistungen != null)
			for(Leistung l : leistungen)
				ausgabe += l.toString() + "\n";
		else
			ausgabe += "keine Leistungen\n";
		return ausgabe;
	}
}

TextIO.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class TextIO implements LesenSchreiben {

	String dateiName;
	
	TextIO(String dateiName)
	{
		this.dateiName = dateiName;
	}
	
	@Override
	public void schreibeDatei(Student[] studenten) throws IOException {
		FileOutputStream fos = new FileOutputStream(dateiName);
		OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF8");	
		
		// string.format()
		String toWrite;
		
		if(studenten != null) {
			// zu schreibenden Text aus einzelnen Elementen zusammensetzen
			toWrite = String.format("%d",studenten.length );
			// Elemente mit ; und Leerzeichen trennen
			toWrite += "; ";
			// Text als Zeile schreiben
			toWrite += "\n";
			osw.write(toWrite);
	
			for(int i=0; i < studenten.length; i++) {
				// neuen Text beginnen
				toWrite = String.format("%d; %s; ",
						studenten[i].matrikelNummer,
						studenten[i].name);
				if(studenten[i].leistungen != null) {
					// Text ergänzen
					toWrite += String.format("%d; ",studenten[i].leistungen.length);

					for(int j=0; j < studenten[i].leistungen.length; j++) {
						toWrite += String.format("%s; %3.1f; ",
								studenten[i].leistungen[j].modul,
								studenten[i].leistungen[j].note);
					}
				}
				else
					toWrite += "0; ";
				// Text / Datensatz eines Studenten als Zeile ausgeben
				toWrite += "\n";
				osw.write(toWrite);
			}
		}
		else
		{
			toWrite = "0; \n";
			osw.write(toWrite);
		}
		osw.close();
		fos.close();
	}

	@Override
	public Student[] leseDatei() throws IOException {
		Student[] geleseneStudenten;

		FileInputStream fis = new FileInputStream(dateiName);
		
		// Einen Scanner erzeugen, der den Stream von Trennzeichen zu Trennzeichen liest
			Scanner scan = new Scanner(fis,"UTF8");
			// ; mit oder ohne folgenden Whitespace (Leerzeichen, Tabulator, Zeilenvorschub)
			// als Trennzeichen festlegen
			scan.useDelimiter(";\\s*");
		
		int studCnt = scan.nextInt();
		if(studCnt != 0)
		{
			geleseneStudenten = new Student[studCnt];
			for(int i=0; i < studCnt; i++) {
				geleseneStudenten[i] = new Student();
				geleseneStudenten[i].matrikelNummer = scan.nextInt();
				geleseneStudenten[i].name = scan.next();
				int leistCnt = scan.nextInt();
				if(leistCnt != 0) {
					geleseneStudenten[i].leistungen = new Leistung[leistCnt];
					for(int j=0; j < leistCnt; j++) {
						geleseneStudenten[i].leistungen[j] = new Leistung();
						geleseneStudenten[i].leistungen[j].modul = scan.next(); 
						geleseneStudenten[i].leistungen[j].note = scan.nextDouble();
					}
				}
				else
					geleseneStudenten[i].leistungen = null;	
			}

		}
		else
			geleseneStudenten = null;

		scan.close();
		fis.close();
		return geleseneStudenten;
	}
	

}

Verwaltung.java

import java.io.IOException;

public class Verwaltung {
	public static void main(String[] args) throws IOException, InterruptedException {
		// Studenten aus dem Speicher abfragen
		Student[] studenten = Speicher.getStudenten();
						
		// Dateihandlerinstanz erzeugen
		LesenSchreiben leseSchreibe = new  
		//		BinaerIO("BinaerDatei");
		//		TextIO("Textdatei");
				JSON_IO("JSON-Datei");
		
		// Datei schreiben
		leseSchreibe.schreibeDatei(studenten);
		System.out.println("Array geschrieben");
		
		// Kurze Wartezeit, simuliert Verarbeitung
		Thread.sleep(1000);
		
		// Datei lesen
		Student[] zurueckGelesen = leseSchreibe.leseDatei();
		System.out.println("Array gelesen");
		
		// Vergleichen
		if(Speicher.sindArraysGleich(studenten, zurueckGelesen))
			System.out.println("Arrays sind gleich");
		else
			System.out.println("Arrays sind ungleich");
	}
}