_fcloseall() bei .NET ?



  • Hallo zusammen, ein gutes neues Jahr 2019. Gibt es bei C# .NET auch eine Methode, die alle geöffneten Dateien schliesst, so wie _fcloseall() bei der Runtime-Library bei C++ MFC ? Gegoogelt habe ich schon, und bei der Windows API nachgeschaut. Weiss jemand Rat ?


  • Administrator

    Also zuerst Mal: _fcloseall ist nicht Teil der MFC noch von C++. Das ist eine C Funktion von Microsoft.

    Für C# erscheint die Funktion etwas fragwürdig. Theoretisch könnte man sie per P/Invoke aufrufen. Darf ich fragen, wozu du das brauchst?



  • Also _fcloseall() ist Bestandteil der Runtime Library die man bei C++ MFC benutzen kann. Nicht bei den MFC selber. Bei C++ MFC habe ich die Funktion eingebaut, mich interessiert, ob man für diese bei C# .NET eine Entsprechung hat. Und zwar reagiert mein C# Programm auf Fehler, indem alle Methoden "false" zurückgeben. Dann müssen aber alle geöffneten Dateien geschlossen werden. Bei C++ MFC geht das mit _fcloseall(). Mich interessiert immer, ob man die Möglichkeiten die man bei C++ MFC hat, auch bei C# .NET hat und umgekehrt. Bei meinem C# .NET Programm, handelt es sich um einen lexikalischen Analysator, den man beim Compilerbau verwenden kann. Der Analysator muss eine Fehlermeldung zurückgeben, wenn der zu analysierende Text lexikalische Fehler enthält. Dann geben alle Funktionen false zurück, es müssen dann aber alle geöffneten Text-Dateien geschlossen werden. In den Texten dürfen auch andere mit include eingebunden werden, so dass man mehrere Text-Dateien schliessen muss.


  • Administrator

    _fcloseall ist eine Microsoft Funktion in der C Library im Header <stdio.h>. Das hat nichts mit C++ oder in irgendeiner Weise dem Framework MFC zu tun: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fclose-fcloseall?view=vs-2017

    Deine Beschreibung, wieso du diese Funktion benötigst, klingt nach grauenhaft schlechtem Softwaredesign. Ich kann dir nur dringend empfehlen dich mit IDisposable, dem using Statement und Exceptions auseinander zu setzen. Wenn ein Fehler passiert, wirfst du eine Exception. Deine Streams sollten sauber IDisposable unterstützen und geschützt sein und alles wird automatisch geschlossen/freigegeben. Es gibt keinen Grund eine Funktion wie _fcloseall hier einzusetzen.



  • Das geht schon, weil alle geöffneten ( includierte ) Dateien in einem Stack eingetragen sind, den muss man nur durchlaufen und jeweils Close() aufrufen. Eigentlich nur eine Frage des Interesses. Gehört vielleicht nicht hierher.



  • Da reden wir wohl aneinander vorbei. Die beschriebenen Fehler macht nicht mein Programm ( der lexikalische Analysator ) selber, sondern im zu analysierenden Text können Fehler enthalten sein. Dann muss mein Programm darauf hinweisen, eventuell noch den Fehler anzeigen. Wenn du mit VS Code schreibst, und begehst einen Syntaxfehler, dann muss der Compiler darauf hinweisen, und nicht auf einen Fehler im Compiler.


  • Administrator

    Eine Exception ist genau das richtige dafür. Eine Exception weisst auf einen Fehler im Programmablauf hin. Der Input hatte einen Fehler drin. Im UI fängst du die Exception ab und zeigst dem Benutzer eine entsprechende Fehlermeldung an.

    Abgesehen davon kannst du IDisposable und co auch ohne Exceptions verwenden. Wenn du aus einem using-Statement rauskommst, wird Dispose aufgerufen.



  • @biter sagte in _fcloseall() bei .NET ?:

    C++ MFC

    Wenn du nochmal "C++ MFC" schreibst bekomm ich 'nen Schreikrampf!



  • Selbst wenn ich eine Exception verwende, müssen die Dateien im Include-Stack gelöscht werden ( close() ), meiner Meinung nach. Wenn mehrere Includes verschachtelt sind, und im Text vom untersten ein Fehler erkannt wird, eine Exception ausgelöst wird, dann müssen die Dateien im Include-Stack gelöscht werden, um einen sauberen Zustand zu hinterlassen. Eigentlich war meine Frage nur, ob es bei C# .NET eine Entsprechung zur _fcloseall() in der stdio gibt.



  • Statt gelöscht meine ich geschlossen, Sorry. Bei Google habe ich nichts gefunden, auch nicht bei der Windows API. Ich glaube, dass es das bei C# .NET gar nicht gibt. Muss man den Vorteil der bessern Kapselung bei .NET mit der grösseren Mächtigkeit ( Meiner Meinung nach ) von MFC wieder verrechnen ?



  • @biter Ich weiß nicht genau, was du mit "include stack" meinst, aber wenn du using-statements mit Exceptions kombinierst dann funktioniert alles richtig. Um den notwendigen Stack kümmert sich dann C# bzw. die Runtime.

    MfG SideWinder



  • Dann versuche ich das eben zu erklären, obwohl es nicht hierher gehört. Ihr wisst ja, dass es bei manchen Programmiersprachen die Möglichkeit gibt andere Texte miteinzubinden. zB: #include <Dateiname>. Diese Includes können verschachtelt sein. Natürlich geht das nicht ins Unendliche, normalerweise ist die Verschachtelungstiefe kleiner zehn. Der Übersetzer der den Text übersetzt, und auf eine Include-Anweisung stösst, legt die Daten die er braucht auf einen Stack ( Hier Include-Stack genannt ) wenn er auf das Ende einer includierten Text-Datei stösst muss er zurückgehen und bei der vorigen Datei weitermachen, an der Stelle hinter der Include-Anweisung ( Die Datei, die die Include-Anweisung enthält). Also im Stack nach oben gehen und wieder zurück. Diese Arbeit übernimmt der lexikalische Analysator. Dann gibt es beim Compilerbau noch die Syntax-Analyse, Codeerzeugung, Optimierung.Die Syntaxanalyse, bestimmt die syntaktische Struktur und erzeugt einen Syntaxbaum. Dabei nimmt sie vom lexikalischen Analysator die Lexeme, also die Textschnippsel, die zusammen gehöhren. zB: die beiden Buchstaben i und f zu if. Also wenn das reicht, bedanke ich mich für die Beiträge, und die Lesezeit. Tschüsss ....



  • Pseudocode:

    text preprocess(filename) {
        open file
        while read line from file
            if line begins with "#include"
                 --> append preprocess(included_filename)
            else --> append line
        close file
        return text
    }
    

    Entweder geht's so oder ich versteh' das Problem nicht.



  • Gute Idee Swordfish, so kann man es machen !



  • Besser noch:

    text preprocess(filename) {
       try
       {
            open file
            while read line from file
            if line begins with "#include"
                 --> append preprocess(included_filename)
            else --> append line
       }
       finally
       {
            close file
       }
       return text
    }
    

    so daß auch bei Exceptions die Datei geschlossen wird - geht sogar eleganter noch mit der using (var file = new XXX(...))-Anweisung (Dispose() schließt automatisch die Datei bzw. den Stream).



  • Die Ideen sind gut, denke meine auch. Die Dateien zu schliessen geht bei mir, indem ich meinen Include-Stack durchlaufe, und jeweils Close() aufrufe.



  • Wobei bei preprocess aus verschachtelten Dateien eine einzige gemacht wird. Der einzige Fehler der da auftreten kann, ist dass open file scheitert. Man erspart sich hier nur die include-Geschichte. Da habe ich noch eine Frage: Wenn preprocess beim dritten Aufruf scheitert ( bei open file ), eine Exception ausgelöst wird, werden dann bei den zwei ersten Aufrufen auch der finally-Teil ausgeführt ? Bin da etwas perplex ...



  • Sorry, dass ich nochmals nerve, mein Programm prüft bei den Include-Dateien auf Zyklizität. Das dürfte bei preprocess nicht gehen, ohne Umwege.



  • @biter sagte in _fcloseall() bei .NET ?:

    Sorry, dass ich nochmals nerve, mein Programm prüft bei den Include-Dateien auf Zyklizität. Das dürfte bei preprocess nicht gehen, ohne Umwege.

    Doch, klar. Wieso nicht?
    Du musst doch bloss irgendwo "mitschreiben" welche Pfade gerade rekursiv bearbeitet werden. Z.B. einfach in einem Member Dictionary<string, object> processingPaths o.ä.



  • @biter Das alles hört sich an, als ob du ein ziemlicher Anfänger in Sachen Programmieren bist. Bist du sicher, daß Compilerbau das richtigetm Thema für deinen Erfahrungsstand ist?