Autor Beitrag
mback2k
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Sa 06.10.07 10:02 
Hallo Leute,

ich habe eine Frage zu der Unit TMemIniFile. Ich habe gesehen, dass diese auf viele Windows Funktionen zurückgreift und weiß nicht wo ich anfangen soll.

Mein Problem: Ich habe verschlüsselte Ini Dateien, um diese zu lesen, muss ich sie also zunächst entschlüsseln, öffnen und wieder verschlüsseln. Wäre es möglich dieses dreimalige öffnen der Dateien in einem einmaligen Prozess unterzubringen? Ich habe das mal versucht, in dem ich mit SetStrings und GetStrings gearbeitet habe und den verschlüsselten Inhalt mithilfe einer Explode Funktion von einem string in eine TStringListe umgewandelt habe, dies hat bei "großen" Dateien (ca. 400 Kb) jedoch viel zu lange gedauert.

Ich kenne mich mit dem Vererben von Klassen noch nicht so gut (lerne es gerade in der Schule) und wäre für jede Hilfe dankbar.

Hier mal mein aktueller Code:
ausblenden volle Höhe 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:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
function TMethods.Hashcode(const text: string): string;
var
  s: string;
  i: integer;
begin
  s := text;
  for i:=1 to length(s) do
    s[i]:=char(120 xor ord(s[i])); // Zahl angepasst.
  result := s;
end;

function TMethods.Hashcode_file(const AFileName: string): bool;
var
  s: string;
  FileSize: integer;
  FileStream: TFileStream;
begin
  if FileExists(AFileName) then
  begin
    FileSize := GetFileSizeEx(AFileName);
    SetLength(s,FileSize);
    FileStream := TFileStream.Create(AFileName,fmOpenReadWrite or fmShareDenyWrite);
    FileStream.Read(s[1],FileSize);
    FileStream.Seek(0,soFromBeginning);
    s := Hashcode(s);
    FileStream.Write(s[1],FileSize);
    FileStream.Destroy;
    result := true;
  end
  else
    result := false;
end;

function TMethods.Hashcode_readIni(const AFileName: string): TMemIniFile;
begin
  if Raw = false then Hashcode_file(AFileName);
  result := TMemIniFile.Create(AFileName);
  if Raw = false then Hashcode_file(AFileName);
end;


Gruß
mback2k
mback2k Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: So 07.10.07 12:19 
Sorry für den bump, aber kennt sich niemand mit der IniFiles Unit aus?
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: So 07.10.07 12:55 
Ich würde das in etwa so lösen: Die verschlüsselte Datei in einen Stream laden und in einen anderen entschlüsseln. In diesem Stream sollte dann "normaler INI-Text" stehen. Dann diese Stringliste aus dem Stream laden und dem MemInifile-Objekt zuweisen. Das sollte auch recht fix gehen.

Nebenbei: Inifiles sind nicht für große Datenmengen gedacht - 400kb sind eigentlich zuviel für sowas. Da wäre evtl. ein ganz anderes Speicherkonzept angebracht.

_________________
We are, we were and will not be.
TheUnknown
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 334



BeitragVerfasst: So 07.10.07 20:48 
user profile iconGausi hat folgendes geschrieben:
Ich würde das in etwa so lösen: Die verschlüsselte Datei in einen Stream laden und in einen anderen entschlüsseln. In diesem Stream sollte dann "normaler INI-Text" stehen. Dann diese Stringliste aus dem Stream laden und dem MemInifile-Objekt zuweisen. Das sollte auch recht fix gehen.

Nebenbei: Inifiles sind nicht für große Datenmengen gedacht - 400kb sind eigentlich zuviel für sowas. Da wäre evtl. ein ganz anderes Speicherkonzept angebracht.


Richtig. Normalerweise spinnt der INI-Zugriff, wenn die Datei über 64Kb geht. Wenn Du unbedingt bei INIs bleiben willst, empfehle ich Dir einen Blick auf BigINI (einfach googlen).
mback2k Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Mo 08.10.07 20:36 
Vielen Dank für diese Informationen. Ich werde mich morgen Nachmittag nochmal damit auseinandersetzen.

Gruß
mback2k
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 08.10.07 20:46 
Moin!

user profile iconTheUnknown hat folgendes geschrieben:
Normalerweise spinnt der INI-Zugriff, wenn die Datei über 64Kb geht.

Das ist für TIniFilekorrekt, AFAIK hat TMemIniFilediese Beschränkung allerdings nicht, da es auch einer TStringListbasiert. Und die wiederum hat die praktischen Methoden .LoadFromStreamund .SaveToStream, mit denen sich Gausis Vorschlag gut umsetzen ließe. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
mback2k Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Di 09.10.07 14:32 
user profile iconNarses hat folgendes geschrieben:
Das ist für TIniFilekorrekt, AFAIK hat TMemIniFilediese Beschränkung allerdings nicht, da es auch einer TStringListbasiert. Und die wiederum hat die praktischen Methoden .LoadFromStreamund .SaveToStream, mit denen sich Gausis Vorschlag gut umsetzen ließe. ;)


Genau dies würde ich ja gerne umsetzen, jedoch benötigt der Constructor von TMemIniFile einen Dateinamen und öffnet die Datei direkt, also würde ich nie unterbinden können, dass die Datei 2mal geöffnet wird, ohne das ich den Constructor abänder, oder?

Wenn ich mir so die Deklaration von TMemIniFile anschaue, stelle ich außerdem fest, dass eben jene StringList in der privaten Variable FSections gespeichert ist, von wo sie mir relativ wenig nützt, oder?

ausblenden 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:
  TMemIniFile = class(TCustomIniFile)
  private
    FSections: TStringList;
    function AddSection(const Section: string): TStrings;
    function GetCaseSensitive: Boolean;
    procedure LoadValues;
    procedure SetCaseSensitive(Value: Boolean);
  public
    constructor Create(const FileName: string);
    destructor Destroy; override;
    procedure Clear;
    procedure DeleteKey(const Section, Ident: String); override;
    procedure EraseSection(const Section: string); override;
    procedure GetStrings(List: TStrings);
    procedure ReadSection(const Section: string; Strings: TStrings); override;
    procedure ReadSections(Strings: TStrings); override;
    procedure ReadSectionValues(const Section: string; Strings: TStrings); override;
    function ReadString(const Section, Ident, Default: string): string; override;
    procedure Rename(const FileName: string; Reload: Boolean);
    procedure SetStrings(List: TStrings);
    procedure UpdateFile; override;
    procedure WriteString(const Section, Ident, Value: String); override;
    property CaseSensitive: Boolean read GetCaseSensitive write SetCaseSensitive;
  end;


Weiteres Problem: Ich lade die verschlüsselten Dateien ja von einem Webserver, der diese generiert. Die PHP Funktionen verschlüsseln eben auch die Zeilenumbrüche und somit kann ich die TStringList Variante auch vergessen, oder?

Irgendwie blick ich da nicht durch :(

Gruß
mback2k
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 09.10.07 16:12 
Moin!

user profile iconmback2k hat folgendes geschrieben:
Genau dies würde ich ja gerne umsetzen, jedoch benötigt der Constructor von TMemIniFile einen Dateinamen und öffnet die Datei direkt, also würde ich nie unterbinden können, dass die Datei 2mal geöffnet wird, ohne das ich den Constructor abänder, oder?
Ich hab mal grad in den VCL-Source (D7pro) geschaut und sehe da IMHO folgende Möglichkeit (ungetestet):
Du erzeugst die Klasseninstanz mit einem Leerstring als Dateiname, machst eine temporäre Stringliste auf und holst da (wie auch immer) die INI-Daten (unverschlüsselt) rein (hier ist also der Entschlüsselungsansatzpunkt!), dann nimmst du .SetStrings(tempSL)von TMemIniFile, um die Daten in die INI-Klasse zu schieben. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
mback2k Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Do 11.10.07 17:50 
Vielen Dank! :) Ich habe mein Problem jetzt folgendermaßen gelöst:

ausblenden volle Höhe 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:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
unit mHashIniFile;

interface

uses
  Windows, SysUtils, Variants, Classes, IniFiles, mMethods;

type
  THashIniFile = class(TMemIniFile)
  private
    HFileName: string;
  public
    constructor Create(const FileName: string);
    procedure UpdateFile; override;
  end;

implementation

constructor THashIniFile.Create(const FileName: string);
var
  FileStrings, FileTemp: string;
  FileSize, FilePosition: integer;
  FileStream: TFileStream;
  FileList: TStringList;
begin
  HFileName := FileName;
  FileSize := Methods.GetFileSizeEx(FileName);
  SetLength(FileStrings,FileSize);
  FileStream := TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite);
  FileStream.Read(FileStrings[1],FileSize);
  FileStream.Seek(0,soFromBeginning);
  FileStrings := Methods.Hashcode(FileStrings);
  FileStream.Free;
  FileList := TStringList.Create;
  FileTemp := '';
  for FilePosition := 1 to Length(FileStrings) do
  begin
    FileTemp := FileTemp + FileStrings[FilePosition];
    if FileStrings[FilePosition] = chr(10) then
    begin
      FileList.Append(FileTemp);
      FileTemp := '';
    end;
  end;
  inherited Create('');
  inherited SetStrings(FileList);
  FileList.Free;
end;

procedure THashIniFile.UpdateFile;
var
  FileStrings: string;
  FilePosition: integer;
  FileList: TStringList;
begin
  FileList := TStringList.Create;
  try
    GetStrings(FileList);
    for FilePosition := 0 to FileList.Count-1 do
      FileStrings := FileStrings + FileList[FilePosition] + chr(10);
    FileStrings := Methods.Hashcode(FileStrings);
    FileList.Clear;
    FileList.Append(FileStrings);
    FileList.SaveToFile(HFileName);
  finally
    FileList.Free;
  end;
end;

end.