Java - Mehrere Dateien einlesen

Fahrradfahrer

Banned
Registriert
Mai 2020
Beiträge
50
Hallo Freunde. Ich bin dabei eine Abwesenheitsverwaltung in Java zu schreiben. In diesem Projekt wird erfasst, welcher Kollege wann krank war, in Urlaub oder auf Dienstreise geht etc.

Natürlich müssen solcherlei Informationen irgendwo abgespeichert werden. Ich habe mir gewisse Datenstrukturen überlegt, um all diese Infos in Objekten abzulegen, die dann serialisierbar sind. Diese Objekte werden von einer Manager-Klasse in Listenform verwaltet und bei Änderungen gespeichert. Ich könnte natürlich dieses Manager-Objekt immer als ganzes abspeichern, sobald sich was ändert. Ich bevorzuge jedoch die kleinsplittrige Lösung, da kleinere Datenmengen schneller abgespeichert sind alsGroße.

Ich bin jedoch mit der Art und Weise, wie ich diese vielen Dateien lade bzw. einlese, schon nicht zufrieden. Es sieht einfach nach unnötig viel Code aus, wobei ich mir aber nicht sicher bin, wie ich das kürzer fassen soll. Wie würdet ihr diesen Ladevorgang im Konstruktor gestalten?


Code:
import java.util.List;
import java.util.ArrayList;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;

public class UrlaubManager {
    private static final Path SAVE_DIR = Paths.get("./save/");
    private static final Path PERSONEN_SAVE_DIR = Paths.get(SAVE_DIR.toString(), "personen");
    private static final Path ABWESENHEITEN_SAVE_DIR = Paths.get(SAVE_DIR.toString(), "abwesenheiten");
    private static final Path ABWESENHEITSGRUENDE_SAVE_DIR = Paths.get(SAVE_DIR.toString(), "abwesenheitsgründe");
    private static final Path GENEHMIGUNGEN_SAVE_DIR = Paths.get(SAVE_DIR.toString(), "genehmigungen");
    private static final Path BERUFSBEZEICHNUNGEN_SAVE_DIR = Paths.get(SAVE_DIR.toString(), "berufsbezeichnungen");

    private List<Person> personen = new ArrayList<>();
    private List<Abwesenheit> abwesenheiten = new ArrayList<>();
    private List<Abwesenheitsgrund> abwesenheitsgruende = new ArrayList<>();
    private List<Genehmigung> genehmigungen = new ArrayList<>();
    private List<Berufsbezeichnung> berufsbezeichnungen = new ArrayList<>();
   
    @SuppressWarnings("unchecked")
    public UrlaubManager() {
        if (Files.exists(SAVE_DIR)) {
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PERSONEN_SAVE_DIR.toFile()))) {
                personen = (ArrayList<Person>) ois.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }

            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(ABWESENHEITEN_SAVE_DIR.toFile()))) {
                abwesenheiten = (ArrayList<Abwesenheit>) ois.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }

            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(ABWESENHEITSGRUENDE_SAVE_DIR.toFile()))) {
                abwesenheitsgruende = (ArrayList<Abwesenheitsgrund>) ois.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }

            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(GENEHMIGUNGEN_SAVE_DIR.toFile()))) {
                genehmigungen = (ArrayList<Genehmigung>) ois.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }
           
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(BERUFSBEZEICHNUNGEN_SAVE_DIR.toFile()))) {
                berufsbezeichnungen = (ArrayList<Berufsbezeichnung>) ois.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                Files.createDirectory(SAVE_DIR);
            } catch (Exception e) {
                e.printStackTrace();
            }

            personen = new ArrayList<>();
            abwesenheiten = new ArrayList<>();
            abwesenheitsgruende = new ArrayList<>();
            genehmigungen = new ArrayList<>();
            berufsbezeichnungen = new ArrayList<>();
        }
    }
}
 
Wie wäre es, wenn du die Daten in einer Datenbank abspeicherst?
Musst nichts super kompliziertes sein, wenn die Firma nicht allzu groß ist.
Beispiel:
  • NoSQL
  • SQLite

 
  • Gefällt mir
Reaktionen: konkretor, S.Kara und Fahrradfahrer
Dein Code ist ja eher nennen wir es gewöhnungsbedürftig... deutsche Variablen.. naja und wie wäre es das in eine Funktion auszulagern das müsste man nicht 5 mal den code duplizieren für jede Liste.

UrlaubsManager ist such nett wieso nicht komplett Deutsch. UrlaubsVerwalter?

Des Weiteren gibt es SqlLight super einfach :)

Und ich hoffe das nur ein Uni Projekt und kein Firmenprojekt das wäre nämlich nicht Datenschutzkonform.
 
  • Gefällt mir
Reaktionen: Fahrradfahrer
blackbirdone schrieb:
das wäre nämlich nicht Datenschutzkonform.
Kannst du das bitte auch begründen? So ganz pauschal sehe ich das nämlich definitiv nicht so.

@Fahrradfahrer Auf jeden Fall solltest du eine kleine Datenbank verwenden. Am besten SQLite, was ja auch schon vorgeschlagen wurde. Das ist sehr einfach und extrem leichtgewichtig. Die Datenbank besteht nur aus einer Datei und einem Treiber um darauf zuzugreifen.
Wie genau das funktioniert erlernst du am besten in einem der unzähligen Tutorials im Netz.
Eine Alternative könnte noch MS Access sein. Da kann man sich solche einfachen Datenbanken mitunter auch sehr schnell zusammenklicken, da kenn ich mich aber nicht besonders aus.
 
  • Gefällt mir
Reaktionen: DubZ
Sieh dir mal lieber ORM Frameworks fuer Java dann an. Sowas wie Hibernate.
 
  • Gefällt mir
Reaktionen: rlchampion
Davon kann ich persönlich nur abraten, wenn man vorher noch nicht mit Datenbanken gearbeitet hat (den Eindruck habe ich jedenfalls). Das macht die Sache hier auch nur unnötig kompliziert, wenn es wirklich nur etwas ganz simples sein soll.
 
  • Gefällt mir
Reaktionen: DubZ
Wie @GTrash81 schon schrieb, nimm SQLite. Das ist nicht kompliziert und auch für Anfänger geeignet.

Falls das kein Lernprojekt sein soll, sondern für den Gebrauch in deiner Firma gedacht ist - nehmt lieber Excel. ;)
 
blackbirdone schrieb:
deutsche Variablen..
(...)
UrlaubsManager ist such nett wieso nicht komplett Deutsch. UrlaubsVerwalter?

Gibt es dafür auch einen Grund oder sprichst du da einfach aus persönlicher Abneigung? Solange es konsistent ist - zumal er ja auch offenbar allein daran arbeitet - ist die Sprache der Bezeichnung doch total egal. Und ja, ich hab auch Clean Code gelesen ;-)
 
  • Gefällt mir
Reaktionen: burglar225
Zum Lernen kann man alles von Hand zu Fuß machen, allerdings würde ich mir von Anfang an versuchen Struktur anzugewöhnen. Der Code zum Laden und Speichern gehört IMHO nicht direkt in die Urlaubsverwaltung. Dafür sollte es eine Abstraktion geben (Stichwort: persistence layer). Das hat den Vorteil, dass man den Teil später austauschen kann, um z.B. eine Datenbank zu verwenden.

Ansonsten wurden ja schon einige Sachen genannt. Duplikation ist schlecht. Fehlerbehandlung fehlt gänzlich, das geht gar nicht. Größere I/O Operationen würde ich nicht im Konstruktur ausführen. Das Verzeichnis zum Speichern nicht hardkodieren.

Um trotzdem mal nur den obigen Code umzuschreiben (Formatierung ist nicht mehrheitskonform):

Java:
public class UrlaubVerwaltung
{
    private static final Path SAVE_DIR = Path.of("save");

    private List<Person> personen = Collections.emptyList();
    private List<Abwesenheit> abwesenheiten = Collections.emptyList();
    private List<Abwesenheitsgrund> abwesenheitsgruende = Collections.emptyList();
    private List<Genehmigung> genehmigungen = Collections.emptyList();
    private List<Berufsbezeichnung> berufsbezeichnungen = Collections.emptyList();

    private void load() throws IOException
    {
        Files.createDirectories(SAVE_DIR);

        personen = load(Daten.PERSONEN);
        abwesenheiten = load(Daten.ABWESENHEITEN);
        abwesenheitsgruende = load(Daten.ABWESENTHEITSGRUENDE);
        genehmigungen = load(Daten.GENEHMIGUNGEN);
        berufsbezeichnungen = load(Daten.BERUFSBEZEICHNUNGEN);
    }

    @SuppressWarnings("unchecked")
    private <T> List<T> load(Daten daten) throws IOException
    {
        Path file = SAVE_DIR.resolve(daten.name + ".rec");

        if (Files.exists(file))
        {
            try (ObjectInputStream in = new ObjectInputStream(Files.newInputStream(file)))
            {
                return (List<T>) in.readObject();
            }
            catch (ClassNotFoundException ex)
            {
                throw new IOException(ex);
            }
        }

        return new ArrayList<>();
    }

    private static enum Daten
    {
        PERSONEN("personen"),
        ABWESENHEITEN("abwesenheiten"),
        ABWESENTHEITSGRUENDE("abwesenheitsgründe"),
        GENEHMIGUNGEN("abwesenheitsgründe"),
        BERUFSBEZEICHNUNGEN("berufsbezeichnungen");

        final String name;

        private Daten(String name)
        {
            this.name = name;
        }
    }
}
 
  • Gefällt mir
Reaktionen: Fahrradfahrer und ReignInBlo0d
burglar225 schrieb:
Eine Alternative könnte noch MS Access sein.
Davon rate ich ab. Wenn man auf eine Datenbank angewiesen ist dann entweder SQLite oder PostgreSql.

Der Datenschützer rennt dir da die Türe ein wenn er sieht das andere möglicherweise nicht berechtigte sehen können wer was genehmigt hat oder ob die Person krank war.
 
  • Gefällt mir
Reaktionen: GTrash81
ModellbahnerTT schrieb:
Der Datenschützer rennt dir da die Türe ein wenn er sieht das andere möglicherweise nicht berechtigte sehen können wer was genehmigt hat oder ob die Person krank war.
Das hat doch nichts mit MS Access zu tun, sondern mit einem entsprechend gesichertem Zugriff. Auch eine SQLite- oder Postgres-DB kann für jeden zugreifbar und kann in diesem Sinne problematisch sein.
 
burglar225 schrieb:
Das hat doch nichts mit MS Access zu tun, sondern mit einem entsprechend gesichertem Zugriff.
Soweit richtig jedoch ist Access eher eine Krankheit die erst ausbricht wenn die Datenbank eine gewisse Komplexität bekommt bzw. Größe dann ist es aber für dieses Projekt vermutlich zu spät. Auch ist es etwas anderes eine SQLite Datenbankdatei zu erkennen als eine .mdb von MS.
 
  • Gefällt mir
Reaktionen: GTrash81
Da widerspreche ich nicht, das habe ich ja selbst schon gesagt.
Du scheinst aber nicht zu wissen, wie Access überhaupt funktioniert, wie man damit arbeitet und welche Möglichkeiten man damit überhaupt hat. Man greift nämlich nicht einfach auf die Datei zu, wie bei SQLite, sondern es geht deutlich weiter.
GERADE für solche Sachen, die sich aller Wahrscheinlichkeit nach eh nie ändern, ist es eigentlich sehr gut geeignet.
Wenn ich mir den Code vom TE oben so anschaue (das ist jetzt nicht so böse gemeint, wie es sich anhört...), dann sollte er ernsthaft über die Variante nachdenken, weil er den Fokus da einfach wo ganz anders hinlegen kann. Programmieren gehört offensichtlich nicht zu seinen Stärken.
Und wenn ich dann lese, wie hier ORM, generische Methoden etc. pp. vorgeschlagen wird, wird das dem TE kaum weiterhelfen. Das ist einfach nicht sein Skilllevel. Daher: Access oder halt bei jemandem in Auftrag geben. Immerhin geht es ums Geschäft und nicht um ein Hobyyprojekt.
 
  • Gefällt mir
Reaktionen: DubZ
schasi schrieb:
Warum ist in der Zeile sowohl <T> als auch List<T>? Eins davon ist der Rückgabewert, aber was ist das andere?

Der Typ Parameter der generischen Methode. Die Listen enthalten unterschiedliche Objekte. Also sollte die Methode auch die unterschiedlichen Typen zurückgeben können. So muss man den Rückgabewert nicht umständlich casten. Wird in der Methode ja ohnehin.
 
So, ich habe jetzt gefunden, wonach ich gesucht habe. Mehrere Dateien lassen sich dadurch einlesen, dass man mehrere StreamReader direkt in der try-Klausel angibt. Ich wusste gar nicht, dass das geht.

Code:
    @SuppressWarnings("unchecked")
    private void load() {
        try (ObjectInputStream oisPersonen = new ObjectInputStream(new FileInputStream(PERSONEN_SAVE_FILE.toFile()));
             ObjectInputStream oisAbwesenheiten = new ObjectInputStream(new FileInputStream(ABWESENHEITEN_SAVE_FILE.toFile()));
             ObjectInputStream oisAbwesenheitsgruende = new ObjectInputStream(new FileInputStream(ABWESENHEITSGRUENDE_SAVE_FILE.toFile()));
             ObjectInputStream oisGenehmigungen = new ObjectInputStream(new FileInputStream(GENEHMIGUNGEN_SAVE_FILE.toFile()));
             ObjectInputStream oisBerufsbezeichnungen = new ObjectInputStream(new FileInputStream(BERUFSBEZEICHNUNGEN_SAVE_FILE.toFile()))) {
            personen = (ArrayList<Person>) oisPersonen.readObject();
            abwesenheiten = (ArrayList<Abwesenheit>) oisAbwesenheiten.readObject();
            abwesenheitsgruende = (ArrayList<Abwesenheitsgrund>) oisAbwesenheitsgruende.readObject();
            genehmigungen = (ArrayList<Genehmigung>) oisGenehmigungen.readObject();
            berufsbezeichnungen = (ArrayList<Berufsbezeichnung>) oisBerufsbezeichnungen.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
 
S.Kara schrieb:
nehmt lieber Excel. ;)
NEIN, bitte nicht :) U.a. du bist es Schuld dass die Unternehmen von klein bis groß noch immer Excel als "Datenbank" missbrauchen.

Und an die ganzen Datenschützer... natürlich kann man Bedenkenlos sqlite und access Dateien DSGVO Konform absichern... passende ACLs konfigurieren und gut ist.
 
  • Gefällt mir
Reaktionen: GTrash81
DubZ schrieb:
NEIN, bitte nicht :) U.a. du bist es Schuld dass die Unternehmen von klein bis groß noch immer Excel als "Datenbank" missbrauchen.
Im Prinzip sind Excel-Arbeitsblätter aber nichts anderes als eine Ansammlung von Daten, oder eine Bank mit Daten. Wozu soll man Excel denn sonst nutzen? Und die Frage ist auch: Wenn so ein Excel-Dokument gescheit strukturiert ist - warum soll man es dann nicht für diesen oder jenen Zweck einsetzen?
 
Es gibt eine Millionen Gründe, warum man Excel nicht als Datenbank verwenden sollte.
Nur weil man es KANN, heißt das noch lange nicht, dass man es auch tun sollte.
Excel ist als Datenbankersatz einfach völlig ineffizient. Ehrlich gesagt verwundert es mich, dass du da jetzt überhaupt etwas einzuwenden hast. Mit dieser Ansicht bist du jedenfalls sehr alleine.
Es mag jetzt auch etwas harsch klingen, aber BITTE lass deine Finger von dem, was du hier anstellen willst und lass es durch einen Profi machen. Der Quellcode, den wir bisher gesehen haben, gehört zum schlechtesten, den ich in meinem ganzen Leben gesehen habe. Ich bezweifle sehr stark, dass ihr wirklich glücklich mit dem Ergebnis werdet. Letztendlich heißt es dann nur wieder "Excel wäre ja doch besser gewesen". Das mag dann zwar stimmen, aber auch nur, weil euer Ersatz dafür nicht schlechter hätte sein können.
Möglichweise (hoffentlich) kommt aber auch alles ganz anders, ich bezweifle es aber.
 
@burglar225

Es gibt eine Millionen Gründe, warum man Excel nicht als Datenbank verwenden sollte.

Die da wären?

Nur weil man es KANN, heißt das noch lange nicht, dass man es auch tun sollte.

Oha, du beeindruckst mit deiner Klugheit.

Excel ist als Datenbankersatz einfach völlig ineffizient.

Wieder eine Behauptung ohne Begründung.

Es mag jetzt auch etwas harsch klingen, aber BITTE lass deine Finger von dem, was du hier anstellen willst und lass es durch einen Profi machen.

Gibt's irgendwelche Zertifikate, an denen ich erkenne, wer ein ominöser "Profi" sein soll?

Der Quellcode, den wir bisher gesehen haben, gehört zum schlechtesten, den ich in meinem ganzen Leben gesehen habe.

Danke. Nach dem Satz weiß ich, dass du keine Ahnung vom Programmieren hast. Du kannst mir ja mal deinen Clean Code zeigen, der würde mich jetzt mal brennend interessieren. Abgesehen davon ist das wieder eine Behauptung, und zwar eine sehr beleidigende und entehrende, ohne jegliche Begründung. Ich ahne schon, was du für einer bist.

Ich bezweifle sehr stark, dass ihr wirklich glücklich mit dem Ergebnis werdet.

Das ist ein privates Projekt und wird nicht arbeitstechnisch oder gar kommerziell eingesetzt.

Letztendlich heißt es dann nur wieder "Excel wäre ja doch besser gewesen". Das mag dann zwar stimmen, aber auch nur, weil euer Ersatz dafür nicht schlechter hätte sein können.

Junge, jetzt komm verdammt nochmal runter von deinem hohen Ross. Was bist du für ein arroganter Zeitgenosse? Arbeitet so jemand wie du mit Menschen zusammen? Du hast von meinem Projekt bis jetzt 20 oder 50 Codezeilen gesehen und bist der Meinung, sagen zu können dass das alles komplett für die Tonne ist? Wie sagenhaft arrogant und widerlich kann ein Mensch sein?

Was genau stört dich denn jetzt schon an dem Code, der da noch nicht mal zu 5 % fertig war? Dass er teilweise deutsch ist? Das ich keine Datenbank verwende? Und wehe, das ist alles. Das rechtfertigt nicht so eine krasse Ehrlosigkeit, wie du sie dir ebend geleistet hast.
 
Zuletzt bearbeitet:
Zurück
Oben