Seite 6 von 7

Verfasst: 21.08.2006 20:28
von Prowokant
@ PMV
Aber es wäre natürlich auch nicht schlecht, wenn FlushFileBuffer() einen Rückgabewert hätte
FlushFileBuffer() liefert einen Rückgabewert (sie dieser Thread)!
die Write-Befehle einen optionalen Parameter, wodurch das direkte schreiben in Dateien möglich ist.
Das geht doch. Du kannst die Größe das Puffers auf 0 setzen!
Ach ja, mich würde mal interezieren, was es noch für Probleme geben kann, außer Speichermedium entfernen oder voll?
Defekte Platten, fehlende Zugriffsberechtigungen, Quota...
Der Fantasie sind keine Grenzen gesetzt, aber das größte
Problem, welches auch häufig vorkommt, ist natürlich,
die volle Platte.

Verfasst: 21.08.2006 20:29
von PMV
Is ja gut ... trink erst mal nen Kamillentee :D

PB hat noch viele Baustellen, die sind mit PB4 nur weniger geworden.
Sich über etwas fehlendes auf zu regen ist bei PB aber fehl am Platz,
zumindest wenn du das hier im deutschen Forum machst. Im englischen
ist die wahrscheinlichkeit, das Fred das liegt wesentlich höher. (100%?)

Naja, wie auch immer ... PB -> do it yourself :lol: /:->
War immer so und wird auch noch lange so bleiben ... das wird oder hat
jeder schmerzlich oder schonender gemerkt.
Ich hab erst vor wenigen Tagen mich mit einem Bug rumschlagen
müssen. Den darf ich immer noch Fred melden, aber noch keine lust öhm
Zeit :freak: ... naja was sollts. Wir sitzten alle im selben Bot.

Aber die Hoffnung stirbt zu letzten, wer nicht so lange warten kann/ will,
dem bleibt leider nur das beiseitelegen von PB ...

Aber danke für den Thread hier Prowokant, wieder was gelernt :D

Edit: Ach ja -.- sorry ... blödes Gedächnis ... ich hab den Thread doch
gelesen :oops: ... naja zu spät.

Zugriffsverletzung, dann können doch Dateien eh nicht angelegt werden.
Du meinst dann, das CreateFile(), ReadFile(), OpenFile() mehr als nur
#False zurück liefern sollten? Ja ... vielleicht funktionier die OnErrorLib()
da mit und liefert das wirkliche problem vielleicht zurück?

Edit2: FlashFileBuffers() liefert bei mir immer "2" zurück? :?

MFG PMV

Verfasst: 21.08.2006 20:41
von Prowokant
@ PMV
Is ja gut ... trink erst mal nen Kamillentee :D
Pfui Spinne.
PB hat noch viele Baustellen, die sind mit PB4 nur weniger geworden.
Sich über etwas fehlendes auf zu regen ist bei PB aber fehl am Platz,
So etwas Triviales wie das Schreiben von Dateien sollte
aber in einer Version 4.x funktionieren, oder?
Naja, wie auch immer ... PB -> do it yourself :lol: /:->
War immer so und wird auch noch lange so bleiben ... das wird oder hat
jeder schmerzlich oder schonender gemerkt.
Das macht PB grundsätzlich interessant. Ich will es ja nur
privat nutzen um mal schnell eine Kleinigkeit zu lösen. Nur
die elementaren Dinge sollten es nicht nötig machen, sich
so lange mit ihnen zu befassen.
Wir sitzten alle im selben Bot.
Ja, ja - die einen rudern und die anderen angeln.

OnErrorLib() - Damit habe ich keinen Wert geliefert bekommen.

Verfasst: 21.08.2006 20:52
von Prowokant
@ PMV
FlashFileBuffers() liefert bei mir immer "2" zurück? :?
Schau dir mal das Codefragment in meinem Posting vom
14 Aug 2006 um 14:15:25h an. Das funktioniert hier
einwandfrei. Wenn du ein WriteStringN machst und
direkt danach den FlushFileBuffers, dann müssen beide
Rückgabewerte identisch sein. Zur Sicherheit könntest du
vorab die Puffergröße ausreichend groß setzen, denn wenn
der WriteStringN in einen Minipuffer schreibt, dann muss
intern schon rausgeschrieben werden. Der anschließende
FlushFileBuffers schreibt dann nur noch den Rest und du
bekommst nur noch die Anzahl der zuletzt noch geschriebenen
Zeichen geliefert. OK?

Verfasst: 21.08.2006 21:35
von PMV
lol ... FlushFileBuffers() gibt ab 4096 Byte immer "2" zurück. Egal was
passiert^^ ... Also bei WriteStringN() 4094 Byte wegen der Zeile-Ende.

Hm, ob der Befehl deswegen undokumentiert ist, oder bedeutet die "2",
das der FileBuffer überschritten war?

Naja ... was sollts. Ach ja, wenn der zu schreibende String zu groß ist für
das Medium, wird bei FlushFileBuffers() überhaupt nichts in die Datei
geschrieben. Ist das nun gut oder schlecht?

MFG PMV

Verfasst: 22.08.2006 10:13
von Prowokant
@ PMV
FlushFileBuffers() gibt ab 4096 Byte immer "2" zurück. Egal was
passiert^^ ... Also bei WriteStringN() 4094 Byte wegen der Zeile-Ende.

Hm, ob der Befehl deswegen undokumentiert ist, oder bedeutet die "2",
das der FileBuffer überschritten war?
Wenn du 4096 Bytes in die Datei schreibst, gilt Folgendes:
1. 4096 ist die Größe des Puffers (Fehlwert)
2. Wird per WriteStringN geschrieben, so werden, wegen CRLF, 4098 Bytes auf die Platte geschrieben.
3. Die ersten 4096 Bytes werden ohne Zutun des Programms rausgeschrieben, weil der Puffer voll ist.
4. Der Puffer enthält danach nur noch CRLF, also 2 Bytes.
5. Das anschließende FlushFileBuffers schreibt den Puffer, also 2 Bytes raus und meldet daher als Rückgabewert 2

Das klappt auch. Ich habe es mit folgendem Code ausprobiert.

Code: Alles auswählen

OpenConsole()
AusgabeDatei$ = "xxx.txt"
If CreateFile(1, AusgabeDatei$)
  FileBuffersSize(1, 4096)
  AusgabeSatz$ = ""
  For II = 1 To 409
    AusgabeSatz$ = AusgabeSatz$ + "1234567890"
  Next
  AusgabeSatz$ = AusgabeSatz$ + "123456"
  RC = WriteStringN(1, AusgabeSatz$)
  RCF = FlushFileBuffers(1)
  PrintN("RC: " + Str(RC) + " / RCF: " + Str(RCF))
  CloseFile(1)
Else
  PrintN("Fehler!")
EndIf
PrintN("Done!")
End
Daher musst du den Puffer so groß wählen, dass der größte zu
schreibende Satz reinpasst. Ansonsten musst du die Bytes
mitzählen, damit du am Ende weißt, was FlushFileBuffers liefern
muss.

Was du aber festgestellt hast, ist IMHO ein Bug in PB. Wenn du
mit einem WriteStringN einen längeren String als die Puffergröße
ausgibst, dann ist das Ergebnis in der Datei zwar u.U. OK, aber
der Rückgabewert ist es nicht. Ich vermute, es kommt zu einem
Pufferüberlauf. Der String wird trotzdem korrekt ausgegeben
und um das CRLF scheint sich PB erst danach zu kümmern.

Dafür spricht auch ein anderer Test. Gibst du zwei Strings aus,
deren gemeinsame Länge die Puffergröße übertrifft, so erkennt
man nach dem FlushFileBuffers, dass dieser den kompletten
zweiten String auf die Platte bringt. Das zeigt, dass PB vor jedem
Write prüft, ob der Puffer noch ausreicht und wenn nicht, wird er
vorher geleert. PB scheint hier also nicht auf Byteebene zu
arbeiten.

Das zuvor Beschriebene macht das Schreiben in die Datei mit dem
Zählen der Bytes nicht einfacher.

Also:
Puffer groß genug wählen und nach jedem Satz ein FlushFileBuffers.
Um Geschwindigkeit zu bringen könnte man ein n-faches eines
maximalen Satzes als Puffer einstellen und nur die Sätze zählen,
aber nicht die Bytes und dann alle n Sätze den FlushFileBuffers
machen.
Wenn man dann ganz auf Nummer Sicher gehen will, dann berechnet
man vor dem WriteStringN die Länge des Strings und gibt, sofern die
Puffergröße überschritten wird, den String in passenden Teilen aus.
Den Aufwand muss man eigentlich auch noch treiben, aber es genügt
wohl, wenn man es nur macht, wenn man bzgl. der Satzlänge nicht
sicher sein kann oder flexibel sein muss.
Ach ja, wenn der zu schreibende String zu groß ist für
das Medium, wird bei FlushFileBuffers() überhaupt nichts in die Datei
geschrieben. Ist das nun gut oder schlecht?
Das ist relativ gleichgültig. Die Hauptsache ist, das Programm
bekommt das mit. Wenn das Schreiben nicht klappt, dann
klappt es halt nicht. Ob das fehlerhafte Ergebnis dann so oder
so aussieht, ist doch egal.

Verfasst: 22.08.2006 12:19
von ts-soft
Immer noch nicht fertig, das Thema :freak:
Notfalls API nehmen, ohne Buffering, weil man seiner Festplatte nicht traut :mrgreen:

Code: Alles auswählen

EnableExplicit

Procedure.s GetLastErrorMsg()
  Protected Buffer.l, Result.s
  FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER|#FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError_(), 0, @Buffer, 0, 0)
  Result = PeekS(Buffer)
  LocalFree_(Buffer)
  ProcedureReturn Result
EndProcedure

Procedure CloseFileEx(hFile.l)
  CloseHandle_(hFile)
EndProcedure

Procedure CreateFileEx(FileName.s)
  Protected hFile.l = CreateFile_(FileName, #GENERIC_WRITE, 0, 0, #CREATE_ALWAYS, #FILE_ATTRIBUTE_NORMAL, #FILE_FLAG_NO_BUFFERING)
  SetLastError_(0)
  If hFile = #INVALID_HANDLE_VALUE
    Debug GetLastErrorMsg()
    ProcedureReturn 0
  Else
    ProcedureReturn hFile
  EndIf  
EndProcedure

Procedure WriteDataEx(hFile.l, *lpBuffer, len)
  Protected written.l
  SetLastError_(0)
  If WriteFile_(hFile, *lpBuffer, len, @written, 0)
    ProcedureReturn written
  Else
    Debug GetLastErrorMsg()
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure WriteStringNEx(hFile.l, String.s)
  String + #CRLF$
  ProcedureReturn WriteDataEx(hFile, @String, Len(String))
EndProcedure
Wenn noch was fehlt (open, read oder ähnlich, bescheid sagen oder die
Konstanten in CreateFileEx anpassen)

Verfasst: 22.08.2006 13:32
von Prowokant
@ ts-soft
Immer noch nicht fertig, das Thema :freak:
Notfalls API nehmen, ohne Buffering, weil man seiner Festplatte nicht traut :mrgreen:
Doch, eigentlich schon und zwar schon lange. :-)

Schönen Dank für deinen Code, aber Windows-Spezialitäten möchte
ich nicht benutzen - aber vielleicht ja jemand anderes. Sicher ist damit
auch eine kugelsichere Lösung machbar.

Verfasst: 22.08.2006 16:45
von PMV
@Prowokant
Danke für deinen Post, nun denn, also hab in in 2 tagen zwei PB-Bugs
gefunden /:-> ... hoffentlich wars das dann jetzt :|


MFG PMV

Verfasst: 22.08.2006 16:58
von ts-soft
Wenn einer immer über Puffer (mehrzahl von ?) scheibt, was soll man da denken? :mrgreen: