studyklar
GdI 1 · Übungsblatt 11 · Aufgabe 4

Binärdatei lesen: Summe des Arrays b

In einer Datei stehen zehn ganze Zahlen, aber nicht als lesbarer Text, sondern als rohe Bytes. Das Programm liest sie, verteilt sie abwechselnd auf zwei Arrays a und b und addiert die Zahlen von b. Rechts stehen die Bytes der Datei und das Programm, die Teile zum aktuellen Schritt sind hervorgehoben.

Die Aufgabe

Übungsblatt 11

Auf die Verwendung der Klassen In und Out soll ab sofort verzichtet werden. Realisieren Sie alle Ein- und Ausgaben mit den Möglichkeiten der Java-Klassenbibliothek.

Aufgabe 11.4

Die jeweils fünf Elemente zweier int-Arrays a und b sind abwechselnd, d. h. in der Reihenfolge a0, b0, a1, b1, a2, …, in der Binärdatei „eingabe_11_4.dat“ abgelegt. Erstellen Sie ein Java-Programm A11_4.java, welches die Summe aller Elemente des Arrays b ermittelt.

Zwei Arrays a und b mit je fünf ganzen Zahlen wurden in eine Datei geschrieben, und zwar im Wechsel: erst a[0], dann b[0], dann a[1] und so weiter. Gesucht ist die Summe der fünf Zahlen von b. Die Datei ist eine Binärdatei: Sie speichert jede Zahl so, wie der Rechner sie intern ablegt, als Bytes. Ein Texteditor zeigt darin nur unlesbare Zeichen.

Das Blatt verlangt außerdem: keine Kursklassen In und Out mehr, sondern nur Klassen aus der Java-Klassenbibliothek.

Merke: Eine Binärdatei liest man mit den Methoden, die zu ihrem Inhalt passen. Hier liegen int-Werte zu je vier Bytes, also liest readInt() von DataInputStream immer genau eine Zahl.
  1. Ansehen, was in der Datei steht.
  2. Verstehen, wie vier Bytes eine Zahl ergeben.
  3. Die Werte a und b zuordnen.
  4. Die Datei im Programm öffnen.
  5. Abwechselnd in a und b lesen.
  6. Die Werte von b addieren.
  7. Das Programm laufen lassen.

Was in der Datei steht

$ xxd eingabe_11_4.dat
00000000: 0000 0003 0000 0002 0000 0008 0000 0006  ................
00000010: 0000 0004 0000 0009 0000 000b 0000 0004  ................
00000020: 0000 0005 0000 0001                      ........

40 Bytes für zehn Zahlen (fünf aus a, fünf aus b): Das sind 40 / 10 = 4 Bytes je Zahl. Genau so viel braucht ein Java-int.

Bevor man ein Programm schreibt, schaut man sich die Datei an. Ein Texteditor hilft bei Bytes nicht. Das Werkzeug xxd (im Terminal von macOS und Linux) zeigt jedes Byte als zweistellige Hexadezimalzahl, also im Zahlensystem zur Basis 16 mit den Ziffern 0 bis 9 und a bis f.

Links steht die Position des ersten Bytes der Zeile (hexadezimal: 10 = 16, 20 = 32), in der Mitte 16 Bytes in Zweiergruppen, rechts der Versuch, sie als Text zu lesen: nur Punkte. Zusammen sind es 16 + 16 + 8 = 40 Bytes.

Vier Bytes ergeben eine Zahl

Stelle 0: Byte 0 bis 3
00 00 00 03=0⋅2563+0⋅2562+0⋅256+3=3\texttt{00 00 00 03} = 0 \cdot 256^3 + 0 \cdot 256^2 + 0 \cdot 256 + 3 = 3
Stelle 6: Byte 24 bis 27
00 00 00 0b=0⋅2563+0⋅2562+0⋅256+11=11\texttt{00 00 00 0b} = 0 \cdot 256^3 + 0 \cdot 256^2 + 0 \cdot 256 + 11 = 11

Ein int besteht aus 32 Bit, also 4 Bytes zu je 8 Bit. Die Datei legt das höchstwertige Byte zuerst ab (Fachwort: big-endian). Jedes Byte hat 256 mögliche Werte (0 bis 255). Wie bei Dezimalziffern zählt jede Stelle weiter links mehr: das letzte Byte einfach, das dritte 256-fach, das zweite 2562256^2-fach und das erste 2563256^3-fach.

In dieser Datei sind die drei vorderen Bytes immer 0. Die Zahl steht also ganz im letzten Byte. Beim Hexwert 0b ist die 0 die erste Stelle und b die zweite. Die Ziffer b steht für elf, also ist 0b = 0 · 16 + 11 = 11.

Aus Skript 6, Folie 6-45 („Ein-/Ausgabe“): Daten werden zeichenweise oder binärcodiert ausgetauscht. Binär wird eine Zahl wie 42 nicht als Zeichen „4“ und „2“ gespeichert, sondern als Bitmuster ihres Werts.
Noch 6 Schritte bis zum Ergebnis
Den ganzen Lösungsweg sehen Studierende und Lehrende der HS KL. Registriere dich mit deiner Adresse @stud.hs-kl.de oder @hs-kl.de, dann geht es hier direkt weiter.

Abbildung 1Binärdatei lesen

DataInputStream, readInt, Summe

Stelle 0, 2, 4, …Stelle 1, 3, 5, …
Stelle 000 00 00 03= ?Byte 0 bis 3
Stelle 100 00 00 02= ?Byte 4 bis 7
Stelle 200 00 00 08= ?Byte 8 bis 11
Stelle 300 00 00 06= ?Byte 12 bis 15
Stelle 400 00 00 04= ?Byte 16 bis 19
Stelle 500 00 00 09= ?Byte 20 bis 23
Stelle 600 00 00 0b= ?Byte 24 bis 27
Stelle 700 00 00 04= ?Byte 28 bis 31
Stelle 800 00 00 05= ?Byte 32 bis 35
Stelle 900 00 00 01= ?Byte 36 bis 39
Summe von b: ?
Legendegerade gemeintDie 40 Bytes der Datei. Warum sie in Vierergruppen stehen, zeigt Schritt 1.

Abbildung 1Binärdatei lesen

DataInputStream, readInt, Summe

import java.io.*; public class A11_4 {     public static void main(String[] args) throws IOException {        FileInputStream fis = new FileInputStream("eingabe_11_4.dat");        DataInputStream dis = new DataInputStream(fis);         int[] a = new int[5];        int[] b = new int[5];        for (int i = 0; i < 5; i++) {            a[i] = dis.readInt();            b[i] = dis.readInt();        }        dis.close();         int sum = 0;        for (int i = 0; i < 5; i++) {            System.out.println("a[" + i + "] = " + a[i] + "   b[" + i + "] = " + b[i]);            sum = sum + b[i];        }        System.out.println("Summe der Elemente von b: " + sum);    }}