一个TMemoryStream的问题,急急 ( 积分: 50 )

  • 主题发起人 主题发起人 pangzhenguang
  • 开始时间 开始时间
P

pangzhenguang

Unregistered / Unconfirmed
GUEST, unregistred user!
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TMyClass=class
public
a,b,c:String;
constructor Create;

end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TMyClass }

constructor TMyClass.Create;
begin
inherited Create;
a:='a';
b:='b';
c:='c';
end;

procedure TForm1.Button1Click(Sender: TObject);
var myclass:TMyClass;
TargetFile: TMemoryStream;
a,b,c:String;
begin
a:='a';
b:='b';
c:='c';
TargetFile := TMemoryStream.Create;
TargetFile.Write(a,SizeOf(a));
TargetFile.Write(b,SizeOf(b));
TargetFile.Write(c,SizeOf(c));
TargetFile.SaveToFile('d:/aaaa.dat') ;
TargetFile.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var TargetFile: TMemoryStream;
a,b,c:String;
begin
TargetFile := TMemoryStream.Create;
TargetFile.LoadFromFile('d:/aaaa.dat');
TargetFile.Read(a,SizeOf(a));
TargetFile.Read(b,SizeOf(b));
TargetFile.Read(c,SizeOf(c));
showmessage(a+';'+b+';'+c);
TargetFile.Free;
end;

end.
上面的代码读出的值没问题,为何下面的有问题呢:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TMyClass=class
public
a,b,c:String;
constructor Create;

end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TMyClass }

constructor TMyClass.Create;
begin
inherited Create;
a:='a';
b:='b';
c:='c';
end;

procedure TForm1.Button1Click(Sender: TObject);
var myclass:TMyClass;
TargetFile: TMemoryStream;
a,b,c:String;
begin
myclass:=TMyClass.Create;
TargetFile := TMemoryStream.Create;
TargetFile.Write(myclass.a,SizeOf(myclass.a));
TargetFile.Write(myclass.b,SizeOf(myclass.b));
TargetFile.Write(myclass.c,SizeOf(myclass.c));
TargetFile.SaveToFile('d:/aaaa.dat') ;
TargetFile.Free;
myclass.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var TargetFile: TMemoryStream;
a,b,c:String;
begin
TargetFile := TMemoryStream.Create;
TargetFile.LoadFromFile('d:/aaaa.dat');
TargetFile.Read(a,SizeOf(a));
TargetFile.Read(b,SizeOf(b));
TargetFile.Read(c,SizeOf(c));
showmessage(a+';'+b+';'+c);
TargetFile.Free;
end;
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TMyClass=class
public
a,b,c:String;
constructor Create;

end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TMyClass }

constructor TMyClass.Create;
begin
inherited Create;
a:='a';
b:='b';
c:='c';
end;

procedure TForm1.Button1Click(Sender: TObject);
var myclass:TMyClass;
TargetFile: TMemoryStream;
a,b,c:String;
begin
a:='a';
b:='b';
c:='c';
TargetFile := TMemoryStream.Create;
TargetFile.Write(a,SizeOf(a));
TargetFile.Write(b,SizeOf(b));
TargetFile.Write(c,SizeOf(c));
TargetFile.SaveToFile('d:/aaaa.dat') ;
TargetFile.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var TargetFile: TMemoryStream;
a,b,c:String;
begin
TargetFile := TMemoryStream.Create;
TargetFile.LoadFromFile('d:/aaaa.dat');
TargetFile.Read(a,SizeOf(a));
TargetFile.Read(b,SizeOf(b));
TargetFile.Read(c,SizeOf(c));
showmessage(a+';'+b+';'+c);
TargetFile.Free;
end;

end.
上面的代码读出的值没问题,为何下面的有问题呢:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TMyClass=class
public
a,b,c:String;
constructor Create;

end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TMyClass }

constructor TMyClass.Create;
begin
inherited Create;
a:='a';
b:='b';
c:='c';
end;

procedure TForm1.Button1Click(Sender: TObject);
var myclass:TMyClass;
TargetFile: TMemoryStream;
a,b,c:String;
begin
myclass:=TMyClass.Create;
TargetFile := TMemoryStream.Create;
TargetFile.Write(myclass.a,SizeOf(myclass.a));
TargetFile.Write(myclass.b,SizeOf(myclass.b));
TargetFile.Write(myclass.c,SizeOf(myclass.c));
TargetFile.SaveToFile('d:/aaaa.dat') ;
TargetFile.Free;
myclass.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var TargetFile: TMemoryStream;
a,b,c:String;
begin
TargetFile := TMemoryStream.Create;
TargetFile.LoadFromFile('d:/aaaa.dat');
TargetFile.Read(a,SizeOf(a));
TargetFile.Read(b,SizeOf(b));
TargetFile.Read(c,SizeOf(c));
showmessage(a+';'+b+';'+c);
TargetFile.Free;
end;
 
应该先释放myclass吧
 
在线等侍。。。提点意见各位高手。。。
 
提点意见各位高手。。。
 
TargetFile.Write(a,SizeOf(a));
SizeOf(a) = 4,写的是a的指针,而不是a字符,下次再读的时候仍然是读取的指针值,也就是地址空间。非常幸运的是在这两次操作之间这个内存空间的内容没有改变,结果一不小心就吧'a' 读了出来

再来看下面这个
TargetFile.Write(myclass.a,SizeOf(myclass.a));
这回写到文件的同样也是指针,只不过指向的是myclass对象的一个内存空间,在这个对象释放后在去相同的地址取值肯定就不对了。
 
提点意见各位高手。。。
 
陈亮亮 那再来看看这个,下面的代码读出来的值也是正确的


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TMyClass }

procedure TForm1.Button1Click(Sender: TObject);
var
TargetFile: TMemoryStream;
a,b,c:String;

begin
a:='我们的电脑';
b:='你们的商店';
c:='中国人';
TargetFile := TMemoryStream.Create;
TargetFile.Write(a,SizeOf(a));
TargetFile.Write(b,SizeOf(b));
TargetFile.Write(c,SizeOf(c));
TargetFile.SaveToFile('d:/aaaa.dat') ;
TargetFile.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var TargetFile: TMemoryStream;
a,b,c:String;
begin
TargetFile := TMemoryStream.Create;
TargetFile.LoadFromFile('d:/aaaa.dat');
TargetFile.Read(a,SizeOf(a));
TargetFile.Read(b,SizeOf(b));
TargetFile.Read(c,SizeOf(c));
showmessage(a+';'+b+';'+c);
TargetFile.Free;
end;

end.
 
当然是对的,这和第一种情况一样

其实问题的关键是在“指针”上面。

如果你写到文件中的是你创建的变量的地址,只要下次读取是这段内存没有被该过的的话读出来的值就是变量的值。
如果是你创建的对象,随后又将对象释放掉了,这个时候在取读就出错了。

还有一点:变量是存在栈空间,对象是在堆中分配空间,这个差异也是造成上述现象的原因。

将一个字符串写到文件中你可以这样做:
TargetFile.Write(a[1], Length(a));
 
陈亮亮, 那应该怎样读写呢
 
var myclass:TMyClass;
TargetFile: TMemoryStream;
a,b,c:String;
llength:integer;
begin
myclass:=TMyClass.Create;
TargetFile := TMemoryStream.Create;

llength:=Length(myclass.a);
TargetFile.Write(llength,SizeOf(llength));
TargetFile.Write(myclass.a[0],llength);

llength:=Length(myclass.b);
TargetFile.Write(llength,SizeOf(llength));
TargetFile.Write(myclass.b[0],llength);

llength:=Length(myclass.c);
TargetFile.Write(llength,SizeOf(llength));
TargetFile.Write(myclass.c[0],llength);

TargetFile.SaveToFile('d:/aaaa.dat') ;
TargetFile.Free;
myclass.Free;

这样写如何正确读出来呢
 
问题还没有解决呀,大家帮帮
 
首先,你可以这样做来读写Myclass.a
a:string;
...
a:=myclass.a;
targetfile.write(a,sizeof(a));
其次,在使用类的时候,不要对该类的实例的域进行操作
应该将其定义为属性。
TMyclass=object
private
fa:string;
public
a;string read fa write fa;
end;
另外,像你这样一个类根本没必要建立类,直接使用record就行了
第三,像上边那位所说
a:string是一个字符串变量
而myclass.a是看作一个指针的
如果把tmyclass定义为record则myclass.a是一个字符串变量
在使用sizeof是会有差异
 
后退
顶部