![]() |
IniFile ReadBinaryStream bekomme ich nicht in Gange
Hallo Community,
ich bekomme immer einen "Stream write error" beim Versuch einen Stream aus einer Ini-Datei zu lesen. Woran kann das liegen? Ich bin mehreren Beispielen gefolgt aber entdecke einfach nicht was da falsch läuft. Vielleicht hat jemand Rat für mich. Hier meine bisherige Bastelei:
Delphi-Quellcode:
und entsprechende Aufrufe
//unit IniHelper;
uses Windows, SysUtils, Classes, SHFolder, IniFiles; ... function GetSpecialFolderPath( Folder: Integer ): string; //const SHGFP_TYPE_CURRENT = 0; var Path: Array [0..MAX_PATH] of WideChar; begin if Windows.Succeeded( SHFolder.SHGetFolderPathW( 0, Folder, 0, SHGFP_TYPE_CURRENT, @Path[ 0 ] ) ) then Result := Path else Result := ''; end; function ReadIniStream( const Filename, Section, Ident: String; const FolderOverride: String = '' ): TStream; var FIniFile: TIniFile; Check: Integer; FName: String; MS: TStream; begin FName := GetSpecialFolderPath( CSIDL_LOCAL_APPDATA ); if FName = '' then Exit; if FolderOverride = '' then FName := FName + '\' + SysUtils.ChangeFileExt( SysUtils.ExtractFilename( ParamStr( 0 ) ), '.' ) + '\' + Filename else FName := FName + '\' + FolderOverride + '\' + Filename; if not FileExists( FName ) then Exit; FIniFile := TIniFile.Create( FName ); try MS := TMemoryStream.Create(); try FIniFile.ReadBinaryStream( Section, Ident, MS ); MS.Position := 0; Result.CopyFrom( MS, MS.Size ); Result.Position := 0; finally MS.Free; end; finally FIniFile.Free; end; end; function WriteIniStream( const Filename, Section, Ident: String; const Value: TStream; const FolderOverride: String = '' ): Boolean; var FIniFile: TIniFile; FName: String; begin Result := False; FName := GetSpecialFolderPath( CSIDL_LOCAL_APPDATA ); if FName = '' then Exit; if FolderOverride = '' then FName := FName + '\' + SysUtils.ChangeFileExt( SysUtils.ExtractFilename( ParamStr( 0 ) ), '.' ) else FName := FName + '\' + FolderOverride; if not SysUtils.ForceDirectories( FName ) then Exit; if Value.Size = 0 then Exit; FIniFile := TIniFile.Create( FName + '\' + Filename ); try Value.Position := 0; FIniFile.WriteBinaryStream( Section, Ident, Value ); finally FIniFile.Free; Result := True; end; end;
Delphi-Quellcode:
Danke fürs Lesen.
procedure TForm1.btnReadClick(Sender: TObject);
var S: String; ms: TStream; begin ms := TMemoryStream.Create(); try S := 'Stream-Error'; ms := IniHelper.ReadIniStream( 'Testfile.cfg', 'Setup', 'StreamEntry' ); S := IntToStr( ms.Size ); Memo1.Lines.Add( 'Stream-Size: ' + S ); ms.Free; except Memo1.Lines.Add( 'Stream-Size: ' + S ); ms.Free; end; end; procedure TForm1.btnWriteClick(Sender: TObject); var s: String; ms: TStream; begin try ms := TMemoryStream.Create(); try S := 'This is a Stream.'; ms.WriteBuffer( S[1], Length( S ) * 2 ); ms.Position := 0; if WriteIniStream( 'Testfile.cfg', 'Setup', 'StreamEntry', ms ) then begin Memo1.Lines.Add( 'StreamEntry Saved.' ) end else begin Memo1.Lines.Add( 'Error: Testfile.cfg Stream could not be created.' ) end; finally ms.Free; end; except Memo1.Lines.Add( 'Error: Fatal Error.' ) end; end; Ps: Speichern klappt, hat nur eine Leseschwäche, genau wie ich :-] |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Wenn du jetzt noch das Result in ReadIniStream initialisierst/erzeugst/den Konstruktor aufrufst, haste es.
Nimm ruhig noch einen Kaffee, es kann nicht schaden! :cheers: |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Lol, jupp Danke klappt!
/edit für die Nachwelt, so isses nu :]
Delphi-Quellcode:
function ReadIniStream( const Filename, Section, Ident: String; const FolderOverride: String = '' ): TStream;
var FIniFile: TIniFile; FName: String; begin FName := GetSpecialFolderPath( CSIDL_LOCAL_APPDATA ); if FName = '' then Exit; if FolderOverride = '' then FName := FName + '\' + SysUtils.ChangeFileExt( SysUtils.ExtractFilename( ParamStr( 0 ) ), '.' ) + '\' + Filename else FName := FName + '\' + FolderOverride + '\' + Filename; if not FileExists( FName ) then Exit; FIniFile := TIniFile.Create( FName ); try Result := TMemoryStream.Create(); try FIniFile.ReadBinaryStream( Section, Ident, Result ); finally Result.Position := 0; end; finally FIniFile.Free; end; end; |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Und Du bist Dir sicher, daß das richtigfunktionier?
verkürzt hast Du:
Delphi-Quellcode:
Wenn Deine er Funktion erfolgreich ist, dann nagelst Du einen zweiten Stream über den ersten oder was?
Funktion Read:TStream;
begin if abbruch then Exit; Result:=TStream.Create; end; //Tuwas MyStream:TStream; MyStream:=TStream.Create; MyStream:=Read; ... MyStream.Free; Das sieht mir sehr nach einem Memory-leak aus. Mach es mit einer Procedure (
Delphi-Quellcode:
) und Du bist auf der sicheren Seite.
read(const mystream:TStream)
Gruß K-H |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab in dem btnReadClick() Aufruf das Create weggelassen. Ich lade bald hoch, will noch ne verschlüßelung einbauen.
für interessierte, das ist es bis jetzt. /edit habs im anhang als komplettes demo projekt zusammengeschnürrt. beim entschlüsseln klappt irgendwas noch nicht, bin an der sache dran. Ps: keine speicherlecks gefunden |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Trotzdem hätte ich das so gemacht (wie p80286 schon sagte):
Delphi-Quellcode:
Zumindest ungefähr so (hab ich nicht in Delphi getestet).
function ReadIniStream( const Filename, Section, Ident: String; const IniStream: TStream; const FolderOverride: String = '' ): Boolean;
var FIniFile: TIniFile; FName: String; FMemStream: TMemoryStream; begin Result:=False; if IniStream<>nil then begin FMemStream := TMemoryStream.Create(); try FName := GetIniFilename( Filename, FolderOverride ); if not SysUtils.FileExists( FName ) then Exit; FIniFile := TIniFile.Create( FName ); FIniFile.ReadBinaryStream( Section, Ident, FMemStream ); FMemStream.Position := 0; IniStream.Position := 0; IniStream.CopyFrom(FMemStream, SizeOf(FMemStream)); Result:=True; finally FMemStream.Free; IniStream.Position := 0; end; end; end; Der Grund ist folgender: Zum einen vertrete ich die Einstellung: Wer etwas erzeugt, der gibt's auch frei. Zum anderen wird zwar in deiner jetzigen Version der Rssultstream auf jeden Fall erzeugt, aber sollte in beim Lesen aus der Ini was schief gehen, gibt sie trotzdem irgendwas zurück. Die aufrufende Methode erfährt davon nichts, und muss dann mit den fehlerhaften Daten weiterarbeiten. Mit o.g. Lösung hätte man schon mal die Info, ob das Lesen des Streams fehlerfrei war. Nun muss man zwar in der aufrufenden Methode den Stream erzeugen (wieder eine Zeile mehr), aber damit erhöht sich m.M.n. die Übersichtlichkeit an der Stelle, wo ich den Stream dann auch wieder freigeben muss. Ist aber nur meine Meinung ;-) |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Dann ist ja fast wie beim ersten mal ^_^
Habe Ratschlag angenommen und umgesetzt: so in der IniHelper.pas
Delphi-Quellcode:
und so in der demo
function ReadIniStream( const Filename, Section, Ident: String; const Value: TStream; const FolderOverride: String = '' ): Boolean;
var FIniFile: TIniFile; FName: String; FMS: TMemoryStream; begin Result := False; if ( Value <> nil ) then begin FMS := TMemoryStream.Create(); try FName := GetIniFilename( Filename, FolderOverride ); if not SysUtils.FileExists( FName ) then Exit; FIniFile := TIniFile.Create( FName ); try FIniFile.ReadBinaryStream( Section, Ident, FMS ); FMS.Position := 0; Value.Position := 0; Value.CopyFrom( FMS, FMS.Size ); finally FIniFile.Free; Value.Position := 0; Result := True; end; finally FMS.Free; end; end; end;
Delphi-Quellcode:
ms := TMemoryStream.Create();
try S := 'Stream-Error'; if IniHelper.ReadIniStream( 'Testfile.cfg', 'Setup', 'StreamEntry', ms ) then begin S := IntToStr( ms.Size ); Memo1.Lines.Add( 'Stream-Size: ' + S ); S := ''; SetLength( S, ms.Size div 2 ); ms.Read( S[1], ms.Size ); Memo1.Lines.Add( 'Stream: ' + S ); ms.Free; end else Memo1.Lines.Add( 'Stream-Error: ' + S ); except Memo1.Lines.Add( 'Stream-Error: ' + S ); ms.Free; end; |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Zitat:
Ansonsten gibst Du Deinen Stream nicht frei wenn IniHelper.ReadIniStream mit false zurückkommt
Delphi-Quellcode:
ms := TMemoryStream.Create();
try try S := 'Stream-Error'; if IniHelper.ReadIniStream('Testfile.cfg', 'Setup', 'StreamEntry', ms) then begin S := IntToStr(ms.Size); Memo1.Lines.Add('Stream-Size: ' + S); S := ''; SetLength(S, ms.Size div 2); ms.Read(S[1], ms.Size); Memo1.Lines.Add('Stream: ' + S); end else Memo1.Lines.Add('Stream-Error: ' + S); finally ms.Free; end; except Memo1.Lines.Add('Stream-Error: ' + S); end; |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Liste der Anhänge anzeigen (Anzahl: 1)
Oh ja, wie wahr! Nun noch mal gefixte version, verschlüßelung funktioniert nun auch :-)
Danke fürs drauf Aufmerksam machen! |
AW: IniFile ReadBinaryStream bekomme ich nicht in Gange
Wohl eher Base64 codiert oder? Zumindest hatte ich bei dir im Codecwas mit base64 gesehen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:53 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz