TStream,TMemoryStream,TStringStream;Pointer,PChar实在分不清,高分求教(300分)

  • 主题发起人 主题发起人 Clark-Kidd
  • 开始时间 开始时间
C

Clark-Kidd

Unregistered / Unconfirmed
GUEST, unregistred user!
1、TMemoryStream和TStringStream有什么区别?什么情况下用哪个?
2、Pointer和PChar好像都是指针类型,什么情况下用哪个?
3、以下2个Buffer什么区别?
Stream.ReadBuffer(var Buffer;Count:Integer);
Richedit1.SetTextBuf(Buffer:PChar);
4、不同类型的Stream,通过存储到1块Buffer区后,是否可以合并和拆分?需要注意什么?
请懂的大侠帮忙解释一下,谢谢!
或者请给我网上资料,最好中文的,英文看这些觉得越看越糊涂,英文学的对不起观众。
请不要介绍书给我,我这里出门买书不方便。
再次谢谢!
 
个人理解:
1。TMemoryStream和TStringStream是从同一个类继承来的,所以他们基本属性类似,但是他们经过不同扩展,又有不同应用,所以也不会有很大区别。TMemoryStream的应用数据类型范围较广,限制较少。TStringStream一般用于字符型数据。其存储方式应该一样的~
2。实际上PChar和Pointer都是地址指针,没有本质区别的!
3。第一个Buffer是数组,大小确定;第二个是地址,大小需要以结束标志“#0”决定。
4。不明白你的意思。
 
[问题1]
其实,各种流在存取、操作数据的机理上都是一样的。说白了,就是“无类型”,它不管
你是整型、字符串型、图象、还是声音,只要你告诉它要读写的数据的首地址和长度,就
可以了。也正是由于这个原因,使用流读写数据的速度都比较快。Delphi之所以还要派生
出各种各样类型的流,其实就是为了使操作某些具体类型的数据时更方便、更容易一些而
已。比如:TMemoryStream中有个Memory属性,它就是这块内存的首地址,使得我们直接
操作内存变得方便了;TStringStream中有个DataString属性,使我们象读一个字符串一
样读取整个流......但话说回来,我偏要用TMemoryStream处理字符串,难道不行吗?当
然行了!或者说处理字符串时用TStringStream就一定最方便吗?不一定啊!你可以看看
我在http://www.delphibbs.com/delphibbs/dispq.asp?lid=1941292这个帖子中的回答,
其中就是用TMemoryStream来处理字符串的,不是很巧妙、很方便吗!

[问题2]
理解指针,主要有两个方面,一个是指针变量本身所占内存的大小,另一个是指针所指向
的数据的数据类型的大小(或长度)。
从前者来看,各种类型的指针都是一样的,都没什么区别,因为在Win32系统下,指针变量
都占4个字节,你可以自己试试,IntToStr(sizeof(Pointer));但从后者来看,就有点不一
样了,这主要就表现在指针移动的步长可能是不一样的,就是说,你让指针移动一个单位,
实际内存中指针移动的字节数是不一样的。请看下面的例子:
var
ms: TMemoryStream;
pInt: ^Integer;
// pInt: PChar;
i: Integer;
j: Integer;
begin
ms := TMemoryStream.Create; //声明并建立一个内存流对象
i := 123;
ms.Write(i, sizeof(Integer)); //向流中写入一个整型值123
i := 99;
ms.Write(i, sizeof(Integer)); //向流中再写入一个整型值99
pInt := ms.Memory; //将这块内存的首地址,也就是指向123的那个地址
//赋给基类型是整型的指针变量pInt
Inc(pInt); //将指针移动一个单位,由于基类型是整型,整型是占4个字节的
//所以,这里虽然只是移动了一个单位,但却相当于移动了4个字节的长度,
//也就是这时指针指向了99这个整数的位置
Move(pInt^, j, sizeof(Integer)); //将99取出来
Caption := IntToStr(j); //显示一下,果然是99
ms.Free;
{
如果将上面的pInt: ^Integer;改成pInt: PChar;其他地方不动,你会发现读出来的数
据不是99,而是内存中的一个随机值,但如果你再将Inc(pInt);改成Inc(pInt, 4);
就正确了。原因就是PChar的基类型是Char,而它是占1个字节的,所以,你移动一个
单位,只移动了一个字节,当然得不到正确的答案了。
}
end;
!!!!这就是各种指针的本质区别!!!!
至于Pointer是无类型的指针,也就是它可以指向任何类型的数据,你将它强制转换成整型,
它就是^Integer,你将它强制转换成字符型,那它就是PChar.....我再将上面的代码改成
Pointer,你就明白了
type
TPInt = ^Integer;
var
ms: TMemoryStream;
pInt: Pointer; //这里
i: Integer;
j: Integer;
begin
ms := TMemoryStream.Create;
i := 123;
ms.Write(i, sizeof(Integer));
i := 99;
ms.Write(i, sizeof(Integer));
pInt := ms.Memory;
Inc(TPInt(pInt)); //这里,其实,使用预定义的整型指针也行,我就是为了说清楚一点
//Inc(PInteger(pInt));
Move(pInt^, j, sizeof(Integer));
Caption := IntToStr(j);
ms.Free;
end;

[问题3]
我同意JamesBond_L的观点,其实Richedit1.SetTextBuf(Buffer:PChar);是在向
剪贴板中写入字符串。

[问题4]
有了问题1中的解答,这个就已经没什么了。合并和拆分都是完全可以的。需要注意的就是
别搞错了起始位置和长度,就可以了。
 
后退
顶部