Seite 4 von 7

Verfasst: 15.08.2006 14:04
von Prowokant
@ ts-soft

> FileBuffersSize(#Datei, 0)

Das ist ja klasse. Habe ich übersehen. Das löst das Problem ja
recht elegant.

> Eine Datei ist normallerweise erst bei CloseFile geschrieben
> und wird auch erst dann geprüft.

Jeder Schreibvorgang auf die Platte führt ggf. zu einem
Fehler, der bei einer Puffergröße von Null natürlich sofort
greift. Na, das ist doch mal was Handfestes.

> Ob ich jede Zeile teste oder am Ende feststelle, es hat
> nicht geklappt, und ich mache Meldung beim User, da ist
> der normalle Weg, am Ende testen, ein vielfaches
> schneller und IMHO genauso sicher.

Das stimmt vielleicht. Stell dir ein Programm vor, das viel
rechnen muss und alle Jubeljahre mal einen Satz schreibt.
Da kann es schon sinnvoll sein, wenn man den Programmlauf
beim ersten Schreibfehler abbrechen kann.
Wenn das nicht relevant ist, dann reicht es vielleicht, nur den
letzten FlushFileBuffers zu prüfen. Was ist aber, wenn der Buffer
zu diesem Zeitpunkt leer ist, der letzte automatisch
ausgeführten FlushFileBuffers aber fehlerhaft ausgeführt
wurde?

Verfasst: 15.08.2006 14:05
von bobobo
Hier noch mein Testprogramm

Code: Alles auswählen

;Ausgabesatz erzeugen
;der sollte in diesem Demo allerdings letztlich mindestens 4096 Byte lang sein
;weil das anscheinend die Größe des Speicherbuffers ist.
;Bei kleineren Werten funktioniert das nicht
;weil der Autor dieser Zeilen noch nie was von Filebuffersize gehört hat
;und sich dafür schämt
For i= 1 To 4096
  Ausgabesatz.s+Chr(Random(26)+45)
Next i
OpenConsole() 
AusgabeDatei$ = "Z:\xxx.txt" 

If OpenFile(1, AusgabeDatei$) 
  FileSeek(1,Lof(1))
  Repeat
    r=WriteStringN(1,Ausgabesatz)
    Print(Str(r))
  Until r<>Len(Ausgabesatz+#CRLF$) ; wegen WriteStringn(), bei writestring() ohne den Anhang
  
  CloseFile(1) 
EndIf
End
Kindergarten ist übrigens gut .. :mrgreen:


Für Programme, die alle Jubeljahre mal was wegschreiben, mach ich es
meist so, dass die zu schreibende Datei kurz vorm schreiben geöffnet
wird und danach wieder geschlossen wird.

hier noch ein Beispiel mit filebuffersize

Code: Alles auswählen

;Ausgabesatz erzeugen in der Länge der FileBuffersize
fbs=1000 ; hier könnten auch andere Werte stehen
For i= 1 To fbs
  Ausgabesatz.s+Chr(Random(26)+45)
Next i
OpenConsole() 
AusgabeDatei$ = "Z:\xxx.txt" 
If OpenFile(1, AusgabeDatei$) 
  FileBuffersSize(1, fbs)
  FileSeek(1,Lof(1))
  Repeat
    r=WriteStringN(1,Ausgabesatz)
    FlushFileBuffers(1)
    PrintN(Str(r)+" "+Str(Len(Ausgabesatz+#CRLF$)))
  Until r<>Len(Ausgabesatz+#CRLF$) ; wegen WriteStringn(), bei writestring() ohne den Anhang
  CloseFile(1) 
EndIf
PrintN("voll?")
Input()
End

Verfasst: 15.08.2006 14:19
von ts-soft
>> Stell dir ein Programm vor, das viel rechnen muss und alle Jubeljahre mal einen Satz schreibt
So ein Programm schreibt nicht alle Jubeljahre einen Satz, sondern erst am
Ende der Berechnungen alle Sätze. Bei sehr vielen, werden diese im Speicher
formatiert und als gesamtes geschrieben.

Selbstverständlich gibt es auch Ausnahmen, wo sensible Daten nicht
verlorengehen dürfen, dort wird meist aber meist auch erst am Ende
geschrieben, lediglich für den Fall der Fälle, wird im Tempordner, wo
immer Platz ist (weil dort auch Windows ist usw.), eine Sicherung erstellt,
die die Daten bei PC-Absturz rekonstruieren kann. Diese Sicherungen
werden meist in einem extra Thread geschrieben, so das das eigentliche
Programm durch langsames Schreiben keine Performanceverluste hat.

Windows selber Cached die Dateien auch alle, kannste ja mal
spasseshalber alles deaktivieren, DMA ausschalten, dann wird Dein PC
schon beim Start ca. 8x solange brauchen

Verfasst: 15.08.2006 16:13
von Prowokant
@ ts-soft

> So ein Programm schreibt nicht alle Jubeljahre einen Satz,
> sondern erst am Ende der Berechnungen alle Sätze. Bei
> sehr vielen, werden diese im Speicher formatiert und als
> gesamtes geschrieben.

OK. Du kannst es dir nicht vorstellen. Schon verstanden.
Es gibt solche Programme. Glaub mir. Reichlich.

Deine übrigen Ausführungen berücksichtigen nicht das
eigentliche Problem. Du musst spätestens am Ende des
Programms feststellen können, ob das Schreiben geklappt
hat. OK, du machst vorher eine Sicherung und was weiß ich
noch, aber am Ende stellt sich die Frage, ob deine neu
erzeugten Daten nun OK sind oder nicht. Du kannst die
Ausgabedatei natürlich händisch prüfen, sofern möglich.
Das will aber doch niemand. Das muss ein Programm
leisten. Ansonsten ist es egal, ob du am Anfang, am Ende
oder immer mal wieder während eines Programmlaufs
schreibst.

> Windows selber Cached die Dateien auch alle, kannste
> ja mal spasseshalber alles deaktivieren, DMA ausschalten,
> dann wird Dein PC schon beim Start ca. 8x solange
> brauchen

Einige PCs brauchen sicher noch länger, aber wen interessiert
das? Ich möchte doch nicht ums Verrecken ohne Pufferung
arbeiten. Ich möchte nur meine Daten auf die Platte
schreiben und mir anschließend sicher sein, dass sie nun
dort stehen. Mehr nicht. Wenn das nur ohne Pufferung geht,
dann geht es eben nur so. Das ist aber ein Problem von PB
und nicht von Windows. Andere Programmiersprachen können
es und machen es. Wie ich schon geschrieben hatte, braucht
PB nur beim WriteStringN das Vorzeichen des Returncodes
ändern, sobald der interne PlattenSync nicht mehr klappt.

Verfasst: 15.08.2006 16:42
von ts-soft
>> braucht PB nur beim WriteStringN das Vorzeichen des Returncodes
Dann müßte PB ja immer sofort schreiben, wäre schrecklich lahm, bzw. ich
kenne keine Programmiersprache die es so Handhabt.

Wenn Du vor CloseFile einmal flashed und der letze Schreibvorgang
erfolgreich war, ist auch der Rest in Ordnung!

Wenn die Datenspeicherung auf USB-Stick oder Diskette erfolgen soll, so
schreib man erstmal auf Festplatte und moved die gesamte Datei, so kann
man testen obs passt und im Fehlerfall bleibt das Orginal auf der Festplatte.

Verfasst: 15.08.2006 17:34
von Prowokant
@ ts-soft

> Dann müßte PB ja immer sofort schreiben, wäre schrecklich
> lahm, bzw. ich kenne keine Programmiersprache die es so
> Handhabt.

Das stimmt doch nicht. PB macht genau das, was es auch nun
schon macht, reicht nur den Returncode des internen
Flush an WriteStringN weiter, der es durch ein negatives
Vorzeichen zeigt. Es gibt bessere Lösung, viel bessere,
aber es wäre allemal besser, als momentan. Nett wäre ein
PB-interner Fehlercode, den man abfragen könnte.

> Wenn Du vor CloseFile einmal flashed und der letze
> Schreibvorgang erfolgreich war, ist auch der Rest in
> Ordnung!

Dann kann man es so machen.

Aber stimmt das?
Was ist, wenn der Buffer zu diesem Zeitpunkt leer ist?
Anders ausgedrückt: Leeren fehlerhafte Schreibversuche
den Buffer?

Verfasst: 21.08.2006 13:53
von Prowokant
Nachdem mir alle so nett geholfen haben, hier noch eine
kleine Nachfrage:
Wie wird denn das Problem bei Preference ("Voreinstellungs-")
Dateien gelöst. Mit FlushFileBuffers geht da ja wohl nichts.
Oder doch?

Verfasst: 21.08.2006 14:02
von Tafkadasom2k5
Was für ein Problem denn?
Die Datei wird geschrieben und dann wird die Datei geschlossen -> folglich auch die Puffer weg geschrieben.

Oder seh ich da was falsch..? :?

Verfasst: 21.08.2006 14:09
von bobobo
Prowokant möchte sicher gehen, dass ein spätestens beim Closepreferences() auch wirklich alles physikalisch geschrieben ist.

IniDateien sind üblicherweise nicht unendlich groß. Der zu
verbrauchenden Platz könnte man vorher versuchen abzuschätzen
und mit dem vorhandenen Platz vergleichen und entsprechend
im Programm reagieren. Also die unvollständige "Doof"-Methode von
oben.

Verfasst: 21.08.2006 14:10
von Prowokant
@ Tafkadasom2k5

Du solltest den Thread vielleicht erst einmal lesen.

Es geht darum, dass die Schreiboperationen keinen
brauchbaren Rückgabewert liefern. Die Operationen
schreiben in den Puffer und das klappt natürlich. Die
eigentliche Schreiboperation auf die Platte, Diskette
oder Sonstetwas geschieht asynchron, wenn der Puffer
voll ist. Wenn es dann zu einem Fehler kommt, weil
z.B. die Platte voll oder kaputt ist, dann bekommt die
Anwendung davon nichts mit und kann folglich auch
nicht auf die Fehlersituation reagieren.