Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Warnung vor OPEN + GET# / PUT#
Gehe zu Seite 1, 2  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 30.05.2024, 14:22    Titel: Warnung vor OPEN + GET# / PUT# Antworten mit Zitat

Wenn man OPEN mit FOR INPUT/OUTPUT statt mit FOR BINARY benutzt, dann lesen/schreiben GET# und PUT# nur eine stark begrenzte Zahl an Bytes - als würde man einen Textstring erwarten.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1230
Wohnort: Ruhrpott

BeitragVerfasst am: 30.05.2024, 18:49    Titel: Antworten mit Zitat

Aus der Referenz:
Zitat:
PUT schreibt Daten in eine Datei, die im BINARY- oder RANDOM-Modus geöffnet wurde.
GET liest Daten aus einer Datei, die im BINARY- oder RANDOM-Modus geöffnet wurde.

Das steht da ja nicht zum Spaß. Wer sich nicht daran hält, muss mit unerwünschten Seiteneffekten rechnen.

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4637
Wohnort: ~/

BeitragVerfasst am: 30.05.2024, 20:40    Titel: Antworten mit Zitat

Oder von der anderen Seite her argumentiert:
FOR INPUT und FOR OUTPUT öffnet die Datei im sequentiellen Modus, ist also auch auf einen sequentiellen Dateizugriff ausgerichtet, nicht auf einen wahlfreien Zugriff.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 31.05.2024, 00:26    Titel: Antworten mit Zitat

nemored hat Folgendes geschrieben:
Oder von der anderen Seite her argumentiert:
FOR INPUT und FOR OUTPUT öffnet die Datei im sequentiellen Modus, ist also auch auf einen sequentiellen Dateizugriff ausgerichtet, nicht auf einen wahlfreien Zugriff.

Die Datenmenge ist aber auch bei simplen sequentiellen Zugriff ohne SEEK begrenzt, ausgerechnet, wenn man die ganze Datei mit einem einzigen GET# einlesen will...

=> sollte unbedingt in die FreeBASIC-Anleitung
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4637
Wohnort: ~/

BeitragVerfasst am: 31.05.2024, 14:41    Titel: Antworten mit Zitat

Sequentielle Daten werden durch bestimmte Zeichen voneinander abgegrenzt (in diesem Fall Komma und Zeilenumbruch). Dass GET# zur Verwendung mit dem Dateimodus BINARY (und RANDOM) vorgesehen ist, steht bereits in der deutschen und der englischen Referenz. Dass GET# im Modus FOR INPUT anders arbeiten sollte als vom Modus FOR INPUT vorgesehen (nämlich bis zum Trennzeichen zu lesen), ist zunächst einmal nicht zu erwarten.

Welche FreeBASIC-Anleitung du meinst, weiß ich nicht. Falls du die Referenz meinst (eine Referenz ist keine Anleitung), da kann ich schon einen Vermerk aufnehmen - allerdings fällt mir da gerade nichts besseres ein als
"Achtung: Wenn Sie GET# in einem anderen Dateimodus verwenden als vorgesehen, kann es sein, dass Sie andere Ergebnisse erhalten als Sie erwarten."
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 31.05.2024, 18:24    Titel: Antworten mit Zitat

nemored hat Folgendes geschrieben:
"Achtung: Wenn Sie GET# in einem anderen Dateimodus verwenden als vorgesehen, kann es sein, dass Sie andere Ergebnisse erhalten als Sie erwarten."

Oder einfach "Wenn man GET# im Modus INPUT statt BINARY verwendet, werden ggf. zu wenig Bytes gelesen." "Man sollte GET# / PUT# immer im Modus BINARY verwenden, auch wenn man keinen beliebigen Dateizugriff benötigt."
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4637
Wohnort: ~/

BeitragVerfasst am: 31.05.2024, 22:09    Titel: Antworten mit Zitat

Das Problem besteht glaube ich darin, was sequentieller Zugriff eigentlich ist. Auch wenn alle Daten am Stück mit einem einzigen GET ausgelesen werden - oder auch in selbst gewählten Blockgrößen nacheinander - handelt es sich dabei nicht um sequentielles Lesen im eigentlichen Sinn. "Wahlfreier Zugriff" zeichnet sich nicht nur dadurch aus, dass du an beliebiger Stelle mit dem Lesen beginnen kannst, sondern auch durch die Möglichkeit, die gelesene Menge selbst zu bestimmen.

Ich habe den Artikel zu FOR INPUT mal etwas ausgebaut; vielleicht ist es so klarer.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 31.05.2024, 22:15    Titel: Antworten mit Zitat

Danke für deine ehrenamtliche Arbeit an der Referenz und dem Forum...

Es ist halt nicht gerade "BASIC-like", also für Programmieranfänger. Mindestens sollte der Compiler dann erzwingen, dass man für GET#/PUT# "BINARY" verwenden muss. Immerhin kommt FreeBASIC meiner Vorstellung eines perfekten (modernen) BASIC immer noch am nächsten.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4637
Wohnort: ~/

BeitragVerfasst am: 01.06.2024, 08:50    Titel: Antworten mit Zitat

Dass BASIC (ganz allgemein) wirklich "BASIC-like" wäre, halte ich nur oberflächlich betrachtet für richtig. Schon der normale INPUT-Befehl ist aus meiner Sicht unnötig kompliziert - was soll diese Unterscheidung mit Strichpunkt oder Komma, mit dem man den Anweisungstext von der Variablenliste abtrennen kann? Und das ist keine Erfindung eines einzelnen BASIC-Dialekts, sondern in allen Dialekten vorhanden, mit denen ich mich bisher beschäftigt habe.

Eine Compiler-Warnung beim Einsatz von GET# auf sequentiell geöffnete Dateien wäre sicher nciht schlecht, ist aber wohl nicht umsetzbar. Ohne Laufzeitanalye kann der Compiler nicht wissen, in welchem Dateimodus die Datei geöffnet ist. Es ist ja z. B. auch möglich, die Datei im Hauptprogramm zu öffnen und die Dateinummer an ein Unterprogramm zu übergeben, oder umgekehrt. In einer interpretierten Sprache kann man dann immer noch einen Fehler werfen; in einem compilierten Programm bringt ein Laufzeitfehler viel Ärger mit sich und wird daher nur in Notfällen geworfen.
(Auch das ist ein Grund, der gegen die "BASIC-likeness" spricht - Compilersprachen sind einfach nicht "anfängerfreundlich".)
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1230
Wohnort: Ruhrpott

BeitragVerfasst am: 02.06.2024, 10:37    Titel: Antworten mit Zitat

Das ist der alte Konflikt Sicherheit vs. Flexibilität.

Ein kleines bisschen Gehirnschmalz sollte der Programmierer schon noch investieren (müssen). lächeln

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 02.06.2024, 16:42    Titel: Antworten mit Zitat

grindstone hat Folgendes geschrieben:
Das ist der alte Konflikt Sicherheit vs. Flexibilität.

Ein kleines bisschen Gehirnschmalz sollte der Programmierer schon noch investieren (müssen). :)

Vorallem aber die Programmierer von Programmiersprachen und Bibliotheken, weniger dessen Nutzer.

Das hier ist nicht der Konflikt "Sicherheit vs. Flexibilität" - den gibt's eigentlich auch nicht, wenn, dann "Sicherheit vs. Performance".

Bei diesem OPEN hat man eine sinnlose "BINARY" Option - Dateien sind eigentlich immer binär, es gibt halt Bytes, mit denen Textfunktionen nicht klar kommen bzw. sind Textdateien Binaries mit bestimmten Regeln. Nach POSIX gibt es schlicht Dateien zum Lesen, Schreiben, neu Erzeugen oder Anhängen, als Primitivstfunktion ein "getchar" (get Byte), das virtuell einfach nur Byte für Byte aus der Datei (eigentlich "Stream") liest.

Dass man ein PRINT# oder INPUT# macht, das Strings liest und ein "Newline" anhängt oder Nullbyte bzw. damit abbricht wäre sinnvoll und logisch. Dass GET# und PUT# nur Bruchteile von einem normalen Speicherpuffer lesen und schreiben, wenn man nicht in einem "BINARY"-Modus ist, den es bei Betriebssystemen gar nicht mal gibt, ist verrückt. Noch nicht mal mit Bequemlichkeit der Programmierer zu erklären...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
hhr



Anmeldungsdatum: 15.07.2020
Beiträge: 102

BeitragVerfasst am: 02.06.2024, 18:44    Titel: Antworten mit Zitat

Ich verstehe das Problem nicht. Man muss doch immer ausprobieren, ob etwas so funktioniert, wie man es wünscht.
Kann mir jemand ein Beispiel nennen, mit dem ich das Problem verstehen kann?

Das folgende Beispiel funktioniert mit Binary genauso wie mit Output/Input:
Code:
dim as string s, file = "test.txt"
dim as string*50 t

s = "123456789" & chr(13,10)

open file for output as #1
put #1,,s
put #1,,s
close #1

open file for input as #1
get #1,,t
close #1

'kill file

print t

sleep
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 02.06.2024, 20:18    Titel: Antworten mit Zitat

hhr hat Folgendes geschrieben:
Ich verstehe das Problem nicht. Man muss doch immer ausprobieren, ob etwas so funktioniert, wie man es wünscht.

Und man muss wissen, wie sich Befehle/Funktionen genau verhalten...

Das Problem ist, dass wenn du ne Datei mit FOR INPUT öffnest, und mit GET# über irgendwas über 3000 Zeichen zu lesen versuchst - eine Datei die entsprechend größer ist einzulesen versuchst, GET# einfach in diesem Bereich abbricht, der Rest vom Puffer sind Nullen.

Beim Testen merkst du erst mal nur, dass es nicht funktioniert. In meinem Fall hat RETROGRA die Fontdatei mit FOR INPUT geöffnet, mein Fonteditor mit FOR BINARY gelesen. Extrem langwieriges Debugging hat erst mal nur rausgefunden, dass der Code absolut perfekt funktioniert, die Fontdatei keinen Fehler enthält usw. Scheinbar hatte FreeBASIC irgendwie einfach keinen Bock, die fehlenden Daten zu kopieren. Zum Schluss konnte ich dann rausfinden, dass eben im Puffer für die Fontdaten plötzlich irgendwo an einer krummen Stelle Schluss war - GET# hat einfach zu lesen aufgehört.

Zum Glück ist der Bug vollkommen verrückt. Würde GET# bei 32768 Bytes abbrechen oder mehr, hätt' ich mich noch mehr rumärgern müssen.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
hhr



Anmeldungsdatum: 15.07.2020
Beiträge: 102

BeitragVerfasst am: 02.06.2024, 21:04    Titel: Antworten mit Zitat

Tatsächlich! Ich habe c16x8.fnt aus retrogra mit folgendem Beispiel kopiert und beide Kopien mit dem Editor geöffnet. Jetzt weiß ich, was gemeint ist.
Könnte das ein Bug sein? Kann das jemand erklären?

(Die Pfade muss man anpassen.)
Code:
dim as string file = "z:\c16x8.fnt"
dim as string*70000 s,t

open file for input as #1
get #1,,s

open file for binary as #2
get #2,,t

open "z:\Kopie-input.txt" for output as #3
put #3,,s

open "z:\Kopie-binary.txt" for output as #4
put #4,,t

close

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
hhr



Anmeldungsdatum: 15.07.2020
Beiträge: 102

BeitragVerfasst am: 02.06.2024, 21:46    Titel: Antworten mit Zitat

Ich habe selbst eine 80KB Textdatei mit Buchstaben erstellt. Damit ist alles in Ordnung. Es wird alles richtig kopiert.
Kann es sein, dass in c16x8.fnt Zeichen oder Zeichenkombinationen vorkommen, die get im Input Modus nicht mag?
Und wenn ja, was ist das, was get im Input Modus nicht mag?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 02.06.2024, 22:01    Titel: Antworten mit Zitat

hhr hat Folgendes geschrieben:
Ich habe selbst eine 80KB Textdatei mit Buchstaben erstellt. Damit ist alles in Ordnung. Es wird alles richtig kopiert.

Mit GET# auf einen Rutsch gelesen ?

hhr hat Folgendes geschrieben:
Kann es sein, dass in c16x8.fnt Zeichen oder Zeichenkombinationen vorkommen die get im Input Modus nicht mag?
Und wenn ja, was ist das, was get im Input Modus nicht mag?

Kann ich mir nicht vorstellen, das einzig Denkbare wären Nullbytes, und davon hat die Datei genug. Es könnte natürlich noch eine "Magic"-Bytefolge geben, aber das ist vorne und hinten einfach alles Quatsch. Die RETROGRA-Dateien findest du bei den Projektvorstellungen, kannst gerne selber Ursachenforschung betreiben. Ob's jetzt mit genau 8192 Bytes oder einem krummen Wert aufgehört hat, kann ich nicht sagen.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
hhr



Anmeldungsdatum: 15.07.2020
Beiträge: 102

BeitragVerfasst am: 03.06.2024, 09:22    Titel: Antworten mit Zitat

Bei get im Input Modus scheint es das EOF-Zeichen Strg+z (&h1a) zu sein. Wenn &h1a in der Datei vorkommt, wird an der Stelle abgebrochen.

Bei get im Binary Modus wird alles gleich behandelt.

https://de.wikipedia.org/wiki/End_of_File

Das folgende Beispiel kopiert 'c16x8.fnt'. Original und Kopie sind identisch:
Code:
dim as string s, file = "z:\c16x8.fnt"

open file for binary as #1
s = space(lof(1))
get #1,,s

open "z:\Kopie-binary.txt" for output as #2
put #2,,s

close

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1230
Wohnort: Ruhrpott

BeitragVerfasst am: 03.06.2024, 10:57    Titel: Antworten mit Zitat

Berkeley hat Folgendes geschrieben:
grindstone hat Folgendes geschrieben:
Das ist der alte Konflikt Sicherheit vs. Flexibilität.

Ein kleines bisschen Gehirnschmalz sollte der Programmierer schon noch investieren (müssen). lächeln

Vorallem aber die Programmierer von Programmiersprachen und Bibliotheken, weniger dessen Nutzer.

Das hier ist nicht der Konflikt "Sicherheit vs. Flexibilität" - den gibt's eigentlich auch nicht, wenn, dann "Sicherheit vs. Performance".

Bei diesem OPEN hat man eine sinnlose "BINARY" Option - Dateien sind eigentlich immer binär, es gibt halt Bytes, mit denen Textfunktionen nicht klar kommen bzw. sind Textdateien Binaries mit bestimmten Regeln. Nach POSIX gibt es schlicht Dateien zum Lesen, Schreiben, neu Erzeugen oder Anhängen, als Primitivstfunktion ein "getchar" (get Byte), das virtuell einfach nur Byte für Byte aus der Datei (eigentlich "Stream") liest.

Dass man ein PRINT# oder INPUT# macht, das Strings liest und ein "Newline" anhängt oder Nullbyte bzw. damit abbricht wäre sinnvoll und logisch. Dass GET# und PUT# nur Bruchteile von einem normalen Speicherpuffer lesen und schreiben, wenn man nicht in einem "BINARY"-Modus ist, den es bei Betriebssystemen gar nicht mal gibt, ist verrückt. Noch nicht mal mit Bequemlichkeit der Programmierer zu erklären...

Die Sache ist doch im Grunde ganz einfach: Mit INPUT/OUTPUT wird die Datei zum sequentiellen Lesen/Schreiben geöffnet, d.h. der Zugriff beginnt ganz vorne und arbeitet sich dann sukzessive bis zum Ende durch. Dabei nimmt dir der Compiler/Interpreter dir die Verwaltung der Datenblöcke ab, er liest/schreibt je Zugriff immer einen Datensatz. Um die erforderlichen Trennzeichen brauchst du dich dabei nicht zu kümmern. Die dazugehörigen Zugriffsbefehle sind INPUT/OUTPUT.

Mit BINARY dagegen öffnest du die Datei für einen wahlfreien Zugriff. Du kannst hier selber bestimmen, an welcher Stelle der Datei du wieviele Bytes lesen möchtest, und du hast Zugriff auf alle Bytes der Datei. Im Gegenzug mußt du dich aber auch selber um die Verwaltung der Daten kümmern. Die dazugehörigen Zugriffsbefehle sind GET/PUT.

Daraus folgt:
Die Befehle GET und PUT sind für den Zugriff auf eine mit INPUT bzw. OUTPUT geöffnete Datei nicht geeignet.

Warum das -wenn auch fehlerhaft- trotzdem funktioniert, hat nemored weiter oben schon erklärt.

Das ist inetwa so, als ob du versuchst, eine Kreuzschraube mit einem Schlitzschraubenzieher festzuziehen: Entweder die Schraubenzieherklinge rutscht ab, oder du beschädigst den Schraubenkopf. Da nutzt es dann auch nichts, auf den Hersteller der Schraube zu schimpfen, der Fehler liegt bei dir, weil du ein falsches Werkzeug benutzt.

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
hhr



Anmeldungsdatum: 15.07.2020
Beiträge: 102

BeitragVerfasst am: 03.06.2024, 12:09    Titel: Antworten mit Zitat

Genau! Get sollte man bei einer für Input geöffneten Datei nicht verwenden. Es sei denn, man wollte nur bis zum ersten &h1A lesen.

Bis jetzt dachte ich, EOF wäre das Ende der Datei. Dass &h1A EOF bedeuten kann, habe ich bis jetzt nicht gewusst.

Dass man Put bei einer für Output geöffneten Datei auch nur mit Vorsicht verwenden sollte, ist wohl nur konsequent.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 46

BeitragVerfasst am: 03.06.2024, 20:20    Titel: Antworten mit Zitat

Es ist schlicht Unsinn, dass man hier unterscheidet. Man nimmt auch keine Schlitzschrauben, sondern Torx ! Klarer Fehler von der Herstellerseite...

Es ist Sache vom Betriebssystem, das Dateiende festzustellen, und das hat bessere Mittel als so was Primitives und Fehleranfälliges wie ein Abschlussbyte. Natürlich sollte man INPUT# und GET# nicht gemischt einsetzen, wenn man nicht weiß was man tut. Dass sich GET# in einer Modusunterscheidung, die es nach POSIX gar nicht gibt, anders verhält, ist... alternatives logisches Denken. Es ist eine Funktionalität, die man EXTRA einprogrammiert hat, und das auch noch anstatt einfach einen Fehler zu schmeißen "Binary-Modus verwenden !"... mit den Augen rollen
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz