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:

Binärdatei lesen (und speichern)

 
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: 29

BeitragVerfasst am: 19.05.2024, 23:23    Titel: Binärdatei lesen (und speichern) Antworten mit Zitat

Code:

DIM AS BYTE PTR buffer
DIM AS INTEGER fn, i

buffer=ALLOCATE(500)

fn=FREEFILE
IF OPEN("file.dat" FOR INPUT AS #fn)=0 THEN
  i=LOF(fn)
  buffer=ALLOCATE(i)
  GET #fn, 0, buffer, i
  CLOSE #fn
ENDIF

funktioniert so und ähnlich ums Verrecken nicht, genausowenig wie PUT #
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1223
Wohnort: Ruhrpott

BeitragVerfasst am: 20.05.2024, 06:49    Titel: Antworten mit Zitat

Hallo,

Dateien, auf die mit GET oder PUT zugegriffen wird, müssen als BINARY geöffnet werden. Außerdem steht das erste Byte der Datei an Position 1, nicht an Position 0.

Und wenn du dem Pointer buffer einen neuen Speicherbereich zuweist, ohne den alten vorher zu deallozieren, bekommst du ein Speicherleck.

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: 29

BeitragVerfasst am: 20.05.2024, 12:30    Titel: Antworten mit Zitat

Danke für die Antwort. Die Dokumentation ist "nicht sehr gut". So einfach und "Anfängerfehler" ist es aber nicht. Anscheinend will GET # (unter Windows) trotz offensichtlichem Datentyp BYTE einen achtmal größeren Speicherblock einlesen, was die Datei nicht mal hergibt.

Nicht gut, vorallem wenn sich FreeBASIC womöglich je nach Version/Plattform anders verhält. Ich muss schauen, dass ich funktionierenden Beispielcode finde. "BINARY", "OUTPUT" und "INPUT" machen keinen Unterschied (und Sinn). Auf den Puffer muss auch byteweise zugegriffen werden können.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Berkeley



Anmeldungsdatum: 13.05.2024
Beiträge: 29

BeitragVerfasst am: 20.05.2024, 14:33    Titel: Antworten mit Zitat

Die Lösung:
Code:

DIM AS UBYTE buffer()
DIM AS INTEGER buffersize
DIM AS INTEGER fileno

IF OPEN("data.dat" FOR BINARY AS #fileno)=0 THEN
  buffersize=LOF(fileno)
  REDIM buffer(buffersize-1)
  GET #fileno, 1, buffer()
  PUT #fileno, 1, buffer()
  CLOSE #fileno
ENDIF

Ob "BINARY" oder "INPUT"/"OUTPUT" scheint keine Rolle zu spielen. Eigentlich sollte man "BINARY ACCESS [READ|WRITE]" schreiben, und bei "INPUT" und "OUTPUT" kann man stattdessen ein Encoding angeben, u.a. "utf8".

LOF() gibt bei mir die Länge um 1 zu groß zurück. Alles in allem nicht sehr gut gemacht :-/ Und wenn schon das Offset 0 einem Index/Stelle 1 entsprechen soll, dann sollte man es konsequent durchziehen; myData(0) sei dann immer falsch, und mit DIM myData(10) gibt es auch ein myData(10) bzw. ist das letzte Feld...

Auf der anderen Seite sollte man beim Programmieren halt auch lernen, wie Computer arbeiten. Von daher ist schwierig was besser ist. Natürlich gibt es im RL keine "Fußnote [0]", man beginnt immer mit "1" zu zählen, hat eine 1. Stelle und keine 0., und wenn man eine Schnittstelle für Menschen programmiert, muss man den Index +1 ausgeben...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



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

BeitragVerfasst am: 20.05.2024, 20:03    Titel: Antworten mit Zitat

Sicherheitshalber mal dazu gesagt: Ein (wasauchimmer) PTR ist immer so groß wie ein INTEGER. Ein BYTE ist 8 Bit groß, ein BYTE PTR dagegen 32 bzw. 64 Bit, je nach Plattform. Ich nehme auch an, dass du Bytes einlesen willst und keine Byte-Adressen?

Das mit dem Start bei 0 oder bei 1 ist in FreeBASIC leider recht inkonsequent; das ist ein Erbe aus QBasic.

Nachtrag: Ich bin mir nicht sicher, aber dass LOF "um 1 zu groß" ist, könnte an einem EOF-Zeichen liegen, mit denen Dateien normalerweise beendet werden, die aber meist ignoriert werden. Weiß da jemand mehr?
_________________
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: 1223
Wohnort: Ruhrpott

BeitragVerfasst am: 20.05.2024, 21:55    Titel: Antworten mit Zitat

Berkeley hat Folgendes geschrieben:
Ob "BINARY" oder "INPUT"/"OUTPUT" scheint keine Rolle zu spielen.
Das stimmt nicht. Beim Öffnen mit OUTPUT wird die Datei neu angelegt, hat also eine Größe von 0. Und in eine mit INPUT geöffnete Datei kann man nicht schreiben.

Berkeley hat Folgendes geschrieben:
Eigentlich sollte man "BINARY ACCESS [READ|WRITE]" schreiben, und bei "INPUT" und "OUTPUT" kann man stattdessen ein Encoding angeben, u.a. "utf8".
ACCESS dient nur dazu, versehentliche unerwünschte Zugriffe (üblicherweise Schreibzugriffe) im weiteren Programmverlauf zu verhindern. Standardmäßig ist eine BINARY-Datei zum Lesen und Schreiben geöffnet. Eine Encoding-Angabe macht nur bei Textdateien Sinn. Mit INPUT und OUTPUT lassen sich aber auch alle anderen Arten von Daten lesen oder schreiben.

Berkeley hat Folgendes geschrieben:
LOF() gibt bei mir die Länge um 1 zu groß zurück.
Das stimmt nicht. Wenn LOF() einen Wert von z.B. 100 zurückgibt, dann ist die Datei auch 100 Bytes groß. Eventuell handelt es sich um einen Text mit angehängtem Zeilenumbruch (CR/LF bei Windows, LF bei Linux).

Berkeley hat Folgendes geschrieben:
Alles in allem nicht sehr gut gemacht :-/ Und wenn schon das Offset 0 einem Index/Stelle 1 entsprechen soll, dann sollte man es konsequent durchziehen; myData(0) sei dann immer falsch, und mit DIM myData(10) gibt es auch ein myData(10) bzw. ist das letzte Feld...
Das ist eines der Fallstricke von FB. Arrays beginnen standardmäßig mit dem Index 0, sofern nicht explizit etwas anderes angegeben wird. Die Indices von myData(10) gehen von 0 bis 10, das sind 11 Elemente.

Dein Codeschnipsel enthält noch einen Fehler, denn die Dateinummer muß zwischen 1 und 255 liegen. Ein Öffnungsversuch mit Dateinummer 0 produziert einen Fehler.
Zur Veranschaulichung habe ich deinen Code mal erweitert:
Code:
ReDim As UByte buffer()
Dim As Integer buffersize
Dim As Integer fileno = FreeFile

Open "data.dat" For Binary As #fileno
Print #fileno, "Hallo Welt"
Close fileno

If Open("data.dat" For Binary As #fileno)=0 Then
  buffersize=Lof(fileno)
  ? "buffersize = ";buffersize
  ?
  ? "LBound ="; LBound(buffer), "UBound = "; UBound(buffer)
  ReDim buffer(buffersize-1)
  ? "LBound ="; LBound(buffer), "UBound = "; UBound(buffer)
  ?
  Get #fileno, 1, buffer()
  For x As Integer = LBound(buffer) To UBound(buffer)
     ? x, buffer(x), Chr(buffer(x))
  Next
  ?
  Put #fileno, 1, buffer()
  ? "LOF = ";Lof(fileno)
  Close #fileno
Else
   ? "FEHLER"
EndIf
Sleep


Guß
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: 29

BeitragVerfasst am: 20.05.2024, 22:24    Titel: Antworten mit Zitat

Das Codeschnipsel war nur ne Veranschaulichung - quasi von der Syntax, ergibt aber keinen Sinn. Von daher egal ob es funktionieren kann. Und "sauberer" Code ist natürlich viel umfangreicher, wie eben das ELSE für die Fehlerbehandlung...

- Stimmt das wirklich, dass man mit DIM x(10) 11 Elemente kriegt ??? Dann war DAS der Bug. Ich habe wohl den REDIM mit dem LOF-Wert -1 gemacht, und dann den LOF-Wert gedumpt und geglaubt, das wär' LOF-1. Da man mit PUT# anscheinend nicht bytegenau schreiben kann, sondern nur die Puffer in voller Länge, war daher die Datei dann um 1 zu groß.

Was ich mit "scheint keine Rolle zu spielen" meinte ist, dass es bezüglich Binärzugriffen keine unerwartbaren Unterschiede gibt. Da Random Access, wird es nur höchstwahrscheinlich keine neue Datei erzeugen und natürlich auch nicht wie APPEND ans Ende einer Datei dranschreiben. Vermutlich spielt das Encoding irgendeine Rolle, wenn man PRINT# und/oder INPUT# benutzt, sehe aber keinen Sinn darin. Ob UTF-8 oder ASCII müssten normal die Stringfunktionen machen, nicht die Dateifunktionen.

Ziemlicher Faux Pas, dass man sich auf die QBasic-Kompatibilität versteift hat. Aus meiner Sicht könnte man ja über die Compiler-Flags alte QBasic-Projekte kompilierbar machen, und mit FreeBASIC eine erheblich abweichende Syntax umsetzen...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



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

BeitragVerfasst am: 20.05.2024, 22:53    Titel: Antworten mit Zitat

Zitat:
- Stimmt das wirklich, dass man mit DIM x(10) 11 Elemente kriegt ???

Ja - ein DIM(10) macht dasselbe wie ein DIM(0 TO 10).

Für binären Zugriff spielt das Encoding keine Rolle, das ist richtig. Binärdaten sind halt Binärdaten.

Zitat:
Ziemlicher Faux Pas, dass man sich auf die QBasic-Kompatibilität versteift hat. Aus meiner Sicht könnte man ja über die Compiler-Flags alte QBasic-Projekte kompilierbar machen, und mit FreeBASIC eine erheblich abweichende Syntax umsetzen...

FreeBASIC war halt zunachst als "QBasic-Klon" angelegt und hat sich erst ab v0.17 deutlich davon abgehoben. Und ab diesem Zeitpunkt war es nicht nur eine Frage, zu QBasic kompatibel zu sein (das ist es sowieso nur noch mittels Compiler-Optionsschalter), sondern auch zu älteren FreeBASIC-Versionen. Allein die saubere Umsetzung von boolschen Variablen hat einige Zeit in Anspruch genommen, weil man nicht die Programme kaputt machen wollte, die in alter Manier Wahrheitswerte in Rechnungen eingebaut haben.
_________________
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
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
Seite 1 von 1

 
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