File Ausgabe, Ablaufinformationen ausgeben

Ich bin neu in Java und habe ein Dateiausgabeproblem.
Ich möchte in der Main-Classe ein Ausgabefile (Textfile) eröffnen und aus anderen Classen beschreiben.
Beim Beenden des Programmes soll der Puffer geleert werden und das File geschlossen werden. Wie kann man das machen.

Hallo,

das habe ich noch nicht genau verstanden, das müsstest du nochmal erklären, was mit anderen Programmen gemeint ist…

aber wahrscheinlich wird am ehesten ein BufferedReader bzw. Writer für deinen Use case geeignet sein. :slight_smile:

hier einfach mal ein Beispiel:

package logs;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Schreiber {
    private static Schreiber INSTANCE = null;
    private static BufferedWriter writer = null;

    public static Schreiber getInstance() {
        if (INSTANCE == null) {
            try {
                INSTANCE = new Schreiber();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return INSTANCE;
    }

    private Schreiber() throws IOException {
        writer = new BufferedWriter(new FileWriter("super wichtiger log.txt"));
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                writer.flush();
                writer.close();
                System.out.println("Writer closed.");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }));
    }

    public void println(String l) {
        try {
            writer.write(l);
            writer.write(System.lineSeparator());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // Put this elsewhere in Your application
    public static void main(String[] args) {
        logs.Schreiber.getInstance().println("Moin");
    }
}

Moin,

kann das sein dass das Forum eine Multiplepersönlichkeit hat und aus Langeweile mit sich selbst redet?

In Ansätzen, wie im Wiki beschrieben:
https://wiki.byte-welt.net/wiki/Text_in_eine_Datei_schreiben_(Java)

Sorry, hier natürlich: private BufferedWriter writer = null; (- static).

Da ist ja alles drin, was einem die Haare zu Berge stehen lässt…

  • Singelton Pattern
  • Work in constructor throwing excreptions
  • Member unnötig mit null initialisiert…

Aber wenigstens sind die Exceptions nicht einfach geschluckt worden.
:grinning:

bye
TT

1 Like

a) BufferedWriter hat auch eine Methode newLine() - da muss man also nicht mit System.lineSeparator arbeiten.

b) statt da einen ShutdownHook zu verwenden (Der nicht zwingend aufgerufen wird!), kann es mehr Sinn machen, bei jedem Schreiben auch direkt ein flush() mit aufzurufen.

c) So Singletons sollte man immer so schreiben, dass diese Thread sicher sind. Das verkompliziert die Sache ja auch nicht wirklich wie z.B. Javabeginners - Singleton-Pattern zeigt. (Wobei es viele Möglichkeiten gibt: static inner class, enum oder eben mit dem doppelten check in einem synchronized Block …)

Und ganz nebenbei: So die Idee wirklich die eines Logfiles ist und es mehr als ein „Ich will das mal selbst entwickeln“ sein sollte: Hier würde ich zu der Verwendung der entsprechenden Klassen / Frameworks raten. So gibt es z.B. java.util.logging das bestimmt einen Blick wert ist. Aber Frameworks gibt es hier auch viele wie log4j, SLF4J, apache, …

Und wenn es um irgend etwas spezielles geht, dann würde ich auch ganz auf ein Singleton verzichten und einen Writer mitgeben (Oder eine eigene Klasse schreiben, die dies dann kapselt). Das gibt dann deutlich mehr Möglichkeiten z.B. beim Testing.

Es hat einen Grund, weshalb ich das explizit so geschrieben habe.

Nach Threadsicherheit wurde nicht gefragt. In der Regel geht man von nicht parallelisierten Anwendungen aus. Das sollte man mit etwas Erfahrung eigentlich wissen.

Eigentlich sollte man nicht auf schlechte Kritik antworten, aber ich wollte die Qualität des Forums nicht deshalb leiden lassen…

Nein, man schreibt generell guten, wiederverwendbaren Code ohne unnötige Einschränkungen.
a) Es ist kein Mehraufwand, das korrekt zu machen.
b) man zeigt anderen nicht etwas, das potentiell Probleme bereiten kann. So lernen Leute schlicht falsche Dinge.

Und bezüglich „nicht parallelisierte Anwendungen“: gerade davon geht man irgendwann nicht mehr aus. Denn jenseits der einfachen „Ich lerne Java“ Anwendungen hat man fast immer mehrere Threads. UI Anwendungen, die auch irgendwelche Dinge macht die nicht sofort fertig sind reichen da schon aus. Aber auch alle anderen Frameworks zu denen man kommt: JEE, Spring, Quarkus, … Sogar parallele Streams reichen schon aus … Das macht es aus meiner Sicht recht fatal, wenn man direkt am Anfang Dinge schon (aus meiner Sicht) falsch gezeigt bekommt.

Und diese Sichtweise findet man auch bei einigen Regeln der üblichen statischen Codeanalyse Tools. Die warnen dann auch bei bestimmten Dingen, weil diese in multithreaded Anwendungen problematisch sein könnten. Und wer etwas Erfahrung hat, der weiss, wie wichtig das ist denn so Probleme sind sehr blöd weil schwer nachstellbar :slight_smile:

Das einfach nur als kleine Begründung meiner Sicht. Du kannst gerne auch noch Argumente für Deine Sichtweise bringen, aber bitte lass Deine Polemik einfach weg. Damit gewinnst Du hier keinen Blumentopf!

1 Like

Ich weiß nicht, ob es schon Populismus ist, wenn man schlicht falsche Antworten auch als solche bennent. Aber wahrscheinlich ja, das ist in Deutschland mittlerweile so.

Und nein, ich baue in eine Anwendung keine Anforderungen ein die es nicht gibt.

Ach Tobias, kann von Dir kein wirkliches Argument kommen?

Ja, Du siehst nur die kleine Anwendung. Dass Code aus dieser Anwendung ggf. in anderen genutzt werden könnte oder sich diese Anwendung weiter entwickeln könnte, siehst Du ganz offensichtlich nicht.
Das ist ok und das darfst Du so sehen. Das ändert aber nichts an meiner Sicht. Und ich denke, dass ich für diese genug Argumente gebracht habe, so dass da jede weitere Diskussion sich erübrigen dürfte.

Singleton threadsafe ist nicht so einfach. Link ist alt aber gut: Singleton Pattern in Java

Was immer der Grund ist, es ist ein schlechter.

Code Qualität und funktionale Sicherheit ist aber immer eine Anforderung.

bye
TT

Der Link ist schon nicht schlecht, aber es gibt bei Singletons eine - aus meiner Sicht sehr einfache - Lösung: Enumerations:

Also einfach ein:

public enum MySingleton {
    INSTANCE;

    // Hier das rein packen, was man braucht....
}

Da spart man sich den ganzen Aufwand mit den static Elementen, private Constructor u.s.w.

Also etwas sehr kurzes und doch effektives.

Siehe dazu ggf. Effective Java 3rd Edition von Joshua Bloch (Item 3). Da werden auch noch paar andere Dinge kurz angerissen bezüglich Inheritance und Serialization.

Generell bin ich kein großer Freund von diesen Singleton Implementationen da dies einfach Tests extrem erschwert. Und meine Erfahrung ist halt auch, dass dies in der Regel daran liegt, dass die Leute zu faul sind, sich um Instanzen und dem Weitergeben dieser zu kümmern.

Alle etwas komplexeren Frameworks kommen meist mit einer Dependency Injection (Welches das Inversion of Control Prinzip umsetzt). Hier gibt es auch den Ansatz eines Singleton - dies aber rein aus Sicht einer zentralen Verwaltungsstelle, die man mit der Erzeugung und Verwaltung von sogenannten Beans beauftragt. Dies bringt einige Vorteile mit sich und dies kann man sich in seine Applikationen einbinden. Ein komplettes Framework wie Spring Boot mag man als Overkill empfinden, aber es gibt auch schon kleinere Lösungen wie Google Guice. Oder wenn man da viele solcher Instanzen hat und man nicht ständig überall zig Parameter bei einem Konstruktor haben will, dann packt man die zusammen in eine Klasse ApplicationContext (oder wie man die auch immer nennen will) und kann da dann die Instanzen, die man sonst als Singleton hätte, sammeln.

Die Kernprobleme mit Singletons mag man am Anfang oft nicht sehen, aber sobald man anfängt, seinen Code mit Unit Tests zu testen, dann wird man in der Regel schnell spüren, dass es nicht wirklich eine gute Idee ist. (Und wenn man ein Test Driven Development praktiziert, dann ist meine Erfahrung, dass man eigentlich auch nie das Bedürfnis spürt, ein Singleton anzulegen.)

Das einfach noch kurz als meine noch etwas ausführlichere Sicht auf dieses Thema.

2 Likes

Ich bin nicht ganz sicher, ob die ursprüngliche Frage wirklich eine Suche nach einer Antwort war. Falls ja, @werben: Vielleicht müßtest du nochmal genauer beschreiben, was du willst. Entweder in Worten, oder mit kleinen Stücken aus deinem aktuellen Code, bei dem du mit einem kurzen // Kommentar beschreibst, was an welcher Stelle genau passieren soll.


Und und auch wenn wir alle wissen, wer - um das mal etwas bullshittig zu formulieren - „ohne hinreichende Anforderungsanalyse“ die erste Antwort mit dem Singleton hier hingeworfen hat, hat sich daraus ja einiges interessantes ergeben.

Über „Code Qualität“ oder „Best Practices“ kann man im Detail oft lange streiten. (Vieles ist aber nicht kontrovers, und gut begründbar).

Bei der Frage, welche Variablen (wann und wie) initialisiert werden, finde ich wichtig, zwischen fields und lokalen Variablen zu unterscheiden. Bei fields könnte man argumentieren, und weiter ausdifferenzieren, ob es denn nun einen default-Konstruktor gibt, oder ob sie final sind oder nicht (und wenn sie final sein könnten, dann sollten sie es sein - das ist einer der weniger kontroversen Punkte…). Bei lokalen Variablen muss ich zugeben, wohl gelegentlich auch mal eine unnötige Initialiserung gemacht zu haben, und da finde ich es nicht schlimm. Es kann einem aber auf den Fuß fallen:

private static void someMethod(boolean someCondition)
{
    // Das bewirkt unten einen Fehler - die value 
    // muss "effectively final" sein
    //String value = null;

    // So funktioniert's:
    String value;
    if (someCondition)
    {
        value = "A";
    }
    else
    {
        value = "B";
    }
    Runnable run = () -> 
    {
        System.out.println(value);
    };
}

Singletons … ein beliebtes Thema. Wenn man sie zum ersten Mal sieht, und nicht viel über OOP weiß, ist die Versuchung groß, zu denken: "Hey, das ist ja voll praktisch, damit kann man überall auf alles zugreifen :slight_smile: ". Aber … irgendwann merkt man, dass diese Einfachheit trügt. Es gibt nur sehr wenige Situationen, wo das „das Pattern der Wahl“ ist.

(Den größten Fauxpas, den ich bisher gesehen habe, war, dass jemand meinte, einen veränderlichen Zustand(!!!) in einem Singleton speichern zu müssen. Man kann sich vorstellen, wie leicht das entgleist: "Hui, in Anwendungsteil A drücke ich einen Button, und in Anwendungsteil B soll sich ein Wert ändern - aber ich will die nicht durch setter+getter miteinander verdrahten. Wie lös’ ich das? Singleton! :bulb: " :woozy_face: )

Alternativen wurden schon angesprochen. Allgemein muss man ohne Singletons dann halt über Strukturen und Verantwortlicheiten und Besitzverhältnise und Initialisierungsreihenfolgen nachdenken - und ‚Nachdenken‘ ist nicht jedermanns Sache… (Und ja, auch da kann man viel falsch machen und/oder zu weit gehen - mein Lieblings-Klassenname ist ja immernoch AbstractSingletonProxyFactoryBean :exploding_head: …)

Aber … dass Singletons (wenn sie überhaupt existieren sollen) threadsicher sein sollten, ist so eine baseline-Anforderung, dass das wohl nicht wirklich kontrovers ist.

2 Likes