AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi IniFile ReadBinaryStream bekomme ich nicht in Gange
Thema durchsuchen
Ansicht
Themen-Optionen

IniFile ReadBinaryStream bekomme ich nicht in Gange

Ein Thema von KodeZwerg · begonnen am 1. Nov 2018 · letzter Beitrag vom 2. Nov 2018
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#1

IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 09:11
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:
//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;
und entsprechende Aufrufe
Delphi-Quellcode:
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;
Danke fürs Lesen.

Ps: Speichern klappt, hat nur eine Leseschwäche, genau wie ich :-]
Gruß vom KodeZwerg

Geändert von KodeZwerg ( 1. Nov 2018 um 09:14 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 09:17
Wenn du jetzt noch das Result in ReadIniStream initialisierst/erzeugst/den Konstruktor aufrufst, haste es.
Nimm ruhig noch einen Kaffee, es kann nicht schaden!
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 09:24
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;
Gruß vom KodeZwerg

Geändert von KodeZwerg ( 1. Nov 2018 um 09:29 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 10:38
Und Du bist Dir sicher, daß das richtigfunktionier?

verkürzt hast Du:
Delphi-Quellcode:
Funktion Read:TStream;
begin
  if abbruch then Exit;
  Result:=TStream.Create;
end;

//Tuwas
MyStream:TStream;

MyStream:=TStream.Create;
MyStream:=Read;
...
MyStream.Free;
Wenn Deine er Funktion erfolgreich ist, dann nagelst Du einen zweiten Stream über den ersten oder was?
Das sieht mir sehr nach einem Memory-leak aus.

Mach es mit einer Procedure (read(const mystream:TStream) ) und Du bist auf der sicheren Seite.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 13:03
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
Angehängte Dateien
Dateityp: 7z IniHelper.7z (4,7 KB, 3x aufgerufen)
Gruß vom KodeZwerg

Geändert von KodeZwerg ( 1. Nov 2018 um 13:30 Uhr)
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
955 Beiträge
 
#6

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 14:22
Trotzdem hätte ich das so gemacht (wie p80286 schon sagte):
Delphi-Quellcode:
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;
Zumindest ungefähr so (hab ich nicht in Delphi getestet).

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
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 15:15
Dann ist ja fast wie beim ersten mal ^_^
Habe Ratschlag angenommen und umgesetzt:

so in der IniHelper.pas
Delphi-Quellcode:
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;
und so in der demo
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;
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 15:32
Habe Ratschlag angenommen und umgesetzt:
und so in der demo
Wenn schon dann so.
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;
Fritz Westermann

Geändert von Fritzew ( 1. Nov 2018 um 16:44 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 18:45
Oh ja, wie wahr! Nun noch mal gefixte version, verschlüßelung funktioniert nun auch

Danke fürs drauf Aufmerksam machen!
Angehängte Dateien
Dateityp: 7z IniHelper.7z (4,7 KB, 5x aufgerufen)
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#10

AW: IniFile ReadBinaryStream bekomme ich nicht in Gange

  Alt 1. Nov 2018, 18:54
Wohl eher Base64 codiert oder? Zumindest hatte ich bei dir im Codecwas mit base64 gesehen.
Michael
Ein Teil meines Codes würde euch verunsichern.

Geändert von Luckie ( 1. Nov 2018 um 18:57 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz