Autor |
Beitrag |
goldensurfer
      
Beiträge: 45
|
Verfasst: Do 17.11.05 19:23
Kann es sein, dass die Streaming-Funktion von Delphi etwas buggy ist?
Folgendes Problem tritt bei mir auf: Ich habe eine Funktion, die eine Datei (Records vom Typ TCacheRec) öffnet und den ersten Record lesen soll.
Die Lösung sieht mit TFilestream folgendermassen aus:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| function TfrmMain.TestDBVersionOkay: Boolean;
var rec: TCacheRec; fs: TFilestream; fnam: String; Excpt: Boolean;
function StreamException(Kind, Filename, ExceptionMessage: String): Boolean; begin MessageDlg('Streamingfehler "' + Kind + '" aufgetreten.' + #13#10 + 'Dateiname: ' + Filename + #13#10 + 'Exception: ' + ExceptionMessage, mtError, [mbOK], 0); result := True; end;
begin
fs := nil; Excpt := False; fNam := 'D:\daten\records.bin';
try fs := TFilestream.Create(fNam, fmOpenRead); try Fillchar(rec, Sizeof(rec), #0); fs.ReadBuffer(rec, Sizeof(rec)); finally fs.Free; end; except on E: EFCreateError do Excpt := StreamException('EFCreateError', fNam, E.Message); on E: EFOpenError do Excpt := StreamException('EFOpenError', fNam, E.Message); on E: EReadError do Excpt := StreamException('EReadError', fNam, E.Message); on E: EWriteError do Excpt := StreamException('EWriteError', fNam, E.Message); else Excpt := StreamException('(unknown)', fNam, '(nicht vorhanden)'); end;
end; |
Beim Start verabschiedet sich die Routine allerdings mit einem EFOpenError. Ich habe daraufhin die Routine mal mit "alten Mitteln" (file of ...) neu geschrieben:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| function TfrmMain.TestDBVersionOkay: Boolean;
var rec: TCacheRec; io: Integer; fc: file of TCacheRec; fnam: String;
begin {$I-} fNam := 'D:\daten\records.bin';
AssignFile(fc, fNam); Reset(fc); io := ioresult;
if io = 0 then begin Read(fc, rec); io := ioresult; end; CloseFile(fc); io := io or ioresult; {$I+} if io <> 0 then ShowMessage('I/O-Fehler Nummer' + IntToStr(io));
end; |
...und siehe da - das Programm arbeitet fehlerfrei.
Zum Thema TFilestream habe ich hier schon einiges im Forum gelesen, auch schon etliche Dinge ausprobiert (Application.ProcessMessages, Delayroutinen) ausprobiert, doch der Fehler bleibt - beim Aufruf des Constructors TFilestream.Create kracht's.
Eine Möglichkeit habe ich gefunden, mit Streams den Fehler zu umgehen, nämlich indem ich die Option fmShareDenyNone mitgebe:
Delphi-Quelltext 1:
| fs := TFilestream.Create(fNam, fmOpenRead or fmShareDenyNone); |
Dann klappt das Lesen der Datei - aber das kann's ja wohl auch nicht sein, oder?
Das Laufwerk, auf dem der Fehler auftritt, ist eine NTFS-Partition. Und jetzt kommt's: wenn ich das Programmverzeichnis auf eine alte Platte kopiere, die im gleichen Rechner hängt, aber FAT32 formatiert ist, funktioniert das Programm auch mit den Filestreams wunderbar!
Hat hier jemand schon mal einen ähnlichen Effekt beobachtet?
Ach ja, andere File-Funktionen der Komponenten, wie z.B. TStringlist.LoadFromFile / SaveToFile funktionieren einwandfrei auf beiden Dateisystemen.
Ciao,
Ralf
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 17.11.05 19:36
Du musst mindestens einen Access-Sharing-Parameter beim Öffnen angegeben haben. fmOpenRead or fmShareDenyWrite funzt bei mir eigentlich immer ...
Wenn, dann kann's nur ein API-Fehler sein und dann wäre mal GetLastError ineressant zu wissen ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
goldensurfer 
      
Beiträge: 45
|
Verfasst: Do 17.11.05 19:50
Ein SetLastError(0) vor dem try-Block und ein
Delphi-Quelltext 1:
| ShowMessage(SysErrorMessage(GetLastError)); |
direkt nach dem Create bringt die Meldung "Klasse ist nicht vorhanden".
Setze ich fmShareDenyNone als Modus, kommt "Vorgang wurde erfolgreich beendet" - aber dann geht ja alles.
Kann es sein, dass meine doch schon recht betagte Delphi-Version (V4.0) mit NTFS-Filesystemen nicht umgehen kann?
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 17.11.05 19:55
D4 hat damit keine Probleme, da es auch nur mit WinAPI kocht ... Ich hab auch D4 und hatte da eigentlich nie Probleme ...
Gib mal die ACLs deiner NTFS-Datei an, auf die Du zugreifen willst.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
goldensurfer 
      
Beiträge: 45
|
Verfasst: Fr 18.11.05 09:54
An die Dateirechte habe ich auch schon gedacht. Die stehen folgendermaßen:
Users: Lesen und Ausführen
Administrators und System: Vollzugriff
Daran kann's aber eigentlich nicht liegen, denn:
1: bin ich mit einem Account mit Admin-Rechten angemeldet
2: wurde die Datei unter demselben User mit demselben Programm erzeugt
3: wenn die Rechte nicht passen würden, würde doch meine zweite Programmvariante (mit "File of TCacheRec") ebenfalls nicht laufen.
Schön aber zu wissen, dass es scheinbar kein reines D4-Problem ist. Aber irgendwo ist der Wurm drin, wenn das Programm mit der Filestream-Variante auf NTFS nicht geht, auf FAT aber schon.
Vielleicht werde ich mir doch mal Delphi2005 von der c't-Heft-CD installieren, nur so zum Vergleichstest. (Kann man die eigentlich parallel installieren oder kommen sich dann diverse DLLs oder dergleichen in die Quere?)
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 18.11.05 19:18
@D9: Jup. Laufen parallel hab auf meinem Rechner von D3-D7 sowie die D9 drauf und die Laufen Problemlos zusammen ...
Zu deinem Problem: Bei den Berechtigungen fehlt mir noch einwas:
1. Onwer: Ist der Owner = Admin ODER ein (normaler) (nichtadminsitrativer) User?
2. Tritt das Problem
a) nur als User
b) nur als Admin
c) immer
auf?
Ich vermute das Problem bei deiner Variante mal darin, dass Du bei NTFS versuchst anderen ein Zugriffsrecht zu nehmen, dass Du selber noch nicht mal besitzt. Frag evtl. mal Luckie Direkt wegenn CreateFile-Berechtigungen an, wie das Sharing gehandhabt wird. Bin mir in der Hinsicht nämlich nicht sicher.
|
|
goldensurfer 
      
Beiträge: 45
|
Verfasst: Mo 21.11.05 10:37
Nein, die Datei wurde ja unter demselben Useraccount angelegt; ein zweiter User greift nicht darauf zu. Der Account hat Admin-Rechte.
Was mich stutzig macht, ist die Tatsache, dass es ohne Stream (also mit "File of...") funktioniert. Ich habe das auch schon mal testweise ausprobiert, mit File of... eine Datei zum Schreiben zu öffne, der ich explizit vorher für den User das Schreibrecht entzogen habe - dann kracht's auch. Logisch, denn Delphi gibt ja die File-Operationen auch nur ans Betriebssystem weiter.
Ich werde mal die D2005 installieren. Trotzdem vielen Dank für die Hilfe an alle.
|
|
|