avoir cette procédure (DELPHI 2010):Problème d'utilisation TEncodedStream avec un TStringList
procedure TfrmMainApp.ChangeLogon;
var
EncStr: TEncodedStream; // from M.Cantu, see below
LogonName : tUserName;
LogonPW : tPassword;
MessageString: string;
begin
if MessageDlg('You are about to change the login to the Connection server. Do you wish to continue?',
mtWarning, [mbYes, mbNo], 0) = mrYes then
begin
LogonName := '';
LogonPW := '';
with dlgPWLogIn do
begin
Caption := 'Change Database Logon';
edtPassword.CharCase := ecNormal;
gbPrompt.Caption := 'Enter User name:';
edtPassword.PasswordChar := #0;
end;
if dlgPWLogIn.ShowModal = mrOK then
begin
LogonName := dlgPWLogIn.edtPassword.Text;
dlgPWLogIn.Release;
Application.CreateForm(TdlgPWLogIn, dlgPWLogIn);
with dlgPWLogIn do
begin
Caption := 'Change Logon';
edtPassword.CharCase := ecNormal;
gbPrompt.Caption := 'Enter Password:';
edtPassword.PasswordChar := cPASSWORD_CHAR;
end;
if dlgPWLogIn.ShowModal = mrOK then
begin
LogonPW := dlgPWLogIn.edtPassword.Text;
FLogParams.Clear;
FLogParams.Add(trim(LogonName));
FLogParams.Add(trim(LogonPW));
//* send and save above params to logon txt file
EncStr := TEncodedStream.Create('dblogon.txt', fmCreate);
try
FLogParams.SaveToStream (EncStr);
// ...
// ...
// ... anything executed here is in error!
finally
begin
EncStr.Free;
end;
end;
end
else
MessageDlg('Cancelled By User.', mtInformation, [mbOK], 0);
end
else
MessageDlg('Cancelled By User.', mtInformation, [mbOK], 0);
end
else
MessageDlg('Cancelled By User.', mtInformation, [mbOK], 0);
end;
PROBLÈME: Tout exécuté après FLogParams.SaveToStream (EncStr) ligne (message exemple d'information) ou après la procédure a exécuté est en erreur :: j'obtiens une erreur ACCES DE VIOLATION sur l'EXE.
J'ai testé la même classe TEncodedStream avec le texte à sauvegarder provenant d'un Tmemo et ça marche bien, donc l'invité est la TStringList utilisée pour contenir le texte temporaire (FLogParams est une TStringList précédemment créée et libérée quand le formulaire est détruit).
THnks pour l'aide.
Remarque: La classe TEncodedStream a été écrite par M.Cantu. Il est le suivant:
unit EncodStr;
Interface
uses
Classes;
type
TEncodedStream = class (TFileStream)
private
FKey: Char;
public
constructor Create(const FileName: string; Mode: Word);
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
property Key: Char read FKey write FKey default 'A';
end;
implementation
constructor TEncodedStream.Create(
const FileName: string; Mode: Word);
begin
inherited Create (FileName, Mode);
FKey := 'A';
end;
function TEncodedStream.Write(const Buffer;
Count: Longint): Longint;
var
pBuf, pEnc: PChar;
I, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// use the buffer as an array of characters
pBuf := PChar (@Buffer);
// for every character of the buffer
for I := 0 to Count - 1 do
begin
// encode the value and store it
EncVal := (Ord (pBuf[I]) + Ord(Key)) mod 256;
pEnc [I] := Chr (EncVal);
end;
// write the encoded buffer to the file
Result := inherited Write (pEnc^, Count);
finally
FreeMem (pEnc, Count);
end;
end;
function TEncodedStream.Read(var Buffer; Count: Longint): Longint;
var
pBuf, pEnc: PChar;
I, CountRead, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// read the encoded buffer from the file
CountRead := inherited Read (pEnc^, Count);
// use the output buffer as a string
pBuf := PChar (@Buffer);
// for every character actually read
for I := 0 to CountRead - 1 do
begin
// decode the value and store it
EncVal := (Ord (pEnc[I]) - Ord(Key)) mod 256;
pBuf [I] := Chr (EncVal);
end;
finally
FreeMem (pEnc, Count);
end;
// return the number of characters read
Result := CountRead;
end;
end.
---------
Exemple of using this class given by M CAntu:
unit EncForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TFormEncode = class(TForm)
Memo1: TMemo;
Memo2: TMemo;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
Panel1: TPanel;
BtnLoadPlain: TButton;
BtnSaveEncoded: TButton;
BtnLoadEncoded: TButton;
Splitter1: TSplitter;
procedure BtnSaveEncodedClick(Sender: TObject);
procedure BtnLoadEncodedClick(Sender: TObject);
procedure BtnLoadPlainClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormEncode: TFormEncode;
implementation
{$R *.DFM}
uses
EncodStr;
procedure TFormEncode.BtnSaveEncodedClick(Sender: TObject);
var
EncStr: TEncodedStream;
begin
if SaveDialog1.Execute then
begin
EncStr := TEncodedStream.Create(SaveDialog1.Filename, fmCreate);
try
Memo1.Lines.SaveToStream (EncStr);
finally
EncStr.Free;
end;
end;
end;
procedure TFormEncode.BtnLoadEncodedClick(Sender: TObject);
var
EncStr: TEncodedStream;
begin
if OpenDialog1.Execute then
begin
EncStr := TEncodedStream.Create(OpenDialog1.FileName, fmOpenRead);
try
Memo2.Lines.LoadFromStream (EncStr);
finally
EncStr.Free;
end;
end;
end;
procedure TFormEncode.BtnLoadPlainClick(Sender: TObject);
begin
if OpenDialog1.Execute then
Memo1.Lines.LoadFromFile (
OpenDialog1.FileName);
end;
end.
=============================
EDITED:
Thanks: Ansifying the TEncodedStream corrected the problem:
unit EncodStr;
interface
uses
Classes;
type
TEncodedStream = class (TFileStream)
private
FKey: ansiChar;
public
constructor Create(const FileName: string; Mode: Word);
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
property Key: ansiChar read FKey write FKey default 'A';
end;
implementation
constructor TEncodedStream.Create(
const FileName: string; Mode: Word);
begin
inherited Create (FileName, Mode);
FKey := 'A';
end;
function TEncodedStream.Write(const Buffer;
Count: Longint): Longint;
var
pBuf, pEnc: PansiChar;
I, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// use the buffer as an array of characters
pBuf := PansiChar (@Buffer);
// for every character of the buffer
for I := 0 to Count - 1 do
begin
// encode the value and store it
EncVal := (Ord (pBuf[I]) + Ord(Key)) mod 256;
pEnc [I] := AnsiChar (EncVal);
end;
// write the encoded buffer to the file
Result := inherited Write (pEnc^, Count);
finally
FreeMem (pEnc, Count);
end;
end;
function TEncodedStream.Read(var Buffer; Count: Longint): Longint;
var
pBuf, pEnc: PansiChar;
I, CountRead, EncVal: Integer;
begin
// allocate memory for the encoded buffer
GetMem (pEnc, Count);
try
// read the encoded buffer from the file
CountRead := inherited Read (pEnc^, Count);
// use the output buffer as a string
pBuf := PansiChar (@Buffer);
// for every character actually read
for I := 0 to CountRead - 1 do
begin
// decode the value and store it
EncVal := (Ord (pEnc[I]) - Ord(Key)) mod 256;
pBuf [I] := ansiChar (EncVal);
end;
finally
FreeMem (pEnc, Count);
end;
// return the number of characters read
Result := CountRead;
end;
end.
Veuillez ne pas appeler 'Trim' sur un mot de passe. Vous devriez accepter chaque caractère verbatim. Si un mot de passe arrive au début ou à la fin avec un espace, alors qu'il en soit ainsi. –
merci pour le fint. – volvox