代码之家  ›  专栏  ›  技术社区  ›  volvox

使用带有tstringlist的腾讯流时出现问题

  •  2
  • volvox  · 技术社区  · 14 年前

    执行此程序(Delphi 2010):

    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; 
    

    问题:在flogparams.savetostream(encstr)行(示例信息消息)之后或在执行过程之后执行的任何操作都存在错误::我在exe上获取访问冲突错误。

    我测试了同一个腾讯流类,其中要保存的文本来自tmemo,它工作正常,因此我认为错误在用于保存临时文本的tstringlist中(flogparams是一个tstringlist,以前在表单被破坏时创建并释放)。


    寻求帮助。

    注:腾讯流类由M.cantu编写。具体如下:

        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.
    
    1 回复  |  直到 14 年前
        1
  •  3
  •   Anya Shenanigans    14 年前

    我附近没有Windows PC来测试它,但是可以猜到,在Delphi2010中,你点击的字符是一个多字节的项目,而腾讯流类中的代码假设字符是一个单字节的项目。应该将腾讯流类中的代码转换为显式使用ansistring/ansichar