高分请问,关于流的使用(100分)

  • 主题发起人 主题发起人 UF
  • 开始时间 开始时间
U

UF

Unregistered / Unconfirmed
GUEST, unregistred user!
TStream
TFileStream
TMemoryStream
这三者的关系和用法,
TMemoryStream.create;
SetSize(Length);
CopyMemory();作用
及Buffer和如何指向内存首地址
 
TFileStream和TMemoryStream是从TStream继承下来的,TStream不能直接创建它的实例。
TFileStream,主要用于文件,TMemoryStream是内存流。更详细的请看书,如果你想做
什么把问题提出来。
 
有一本古老的书《精通delphi》姚庭宝 主编 电子工业出版社 471至490页
有电子版,看看或许有帮助。
 
精通delphi何处有下
 
小弟用MTS做一接口, 有两个参数,一个是把数据读到内存中, 根据数据长度,
创建一内存区域,处理一些情况,然后用另一参数读出来数据.
 
用TMemoryStream可能比较好和简单
 
这种问题还是看书的好,这种基础性的东西在这里是说不清楚的。
 
UF:
请将问题说清楚些,举例说明,两个参数都是什么
 
可以看一下DELPHI中自带的源程序,TMETAFILE有MEMORYSTREAM的用法,TSTRINGLIST的LOADFROMFILE中
TFILESTREAM的用法。
 
---- 在Dephi中提供了一个抽象的数据类型TStream来支持对流式数据的操作。这些数据通常来自文件、数据库、内存对象、OLE对象等,TStream提供了统一、简洁的方法来进行数据的读写。在通常情况下,我们并不需要直接使用TStream类,对流式数据的读写封装在VCL控件的方法中。但是如果这些方法无法满足我们的要求,就需要自己手动控制数据的读写。
to PoleStar :
流一般包括文件流(FileStream)和内存流(MemoryStream),但是最基本的还是Stream的操作,
相信下面的讲解会对你有所帮助.
一、 TStream的常用的方法和属性:
 
---- 1. function Read(var Buffer;
Count: Longint): Longint;
virtual;
abstract
---- 2. function Write(const Buffer;
Count: Longint): Longint;
virtual;
abstract;

---- 3. function Seek(Offset: Longint;
Origin: Word): Longint;
virtual;
abstract;

---- 4. property Position: Longint;

---- 5. property Size: Longint
---- Read,Write,Seek都是纯虚函数,提供了数据读写和定位的抽象的方法。Read方法将数据从Stream中读到Buffer缓冲区中,Write则实现相反的操作,返回值表示实际读写数据的大小。Seek提供了在Stream中移动数据指针的方法。参数Origin可以取soFrombegin
ning,soFromCurrent,soFromEnd 三个值,Offset是偏移量,返回值是当前Stream数据指针的位置。
---- Position表示了数据指针在Stream中的位置。这个属性是可读写的,它实际上就是通过调用Seek方法实现的,所以实际使用时使用这个属性更为方便一些。Size属性表示当前Stream的大小,对于不同的Stream,有些时候是只读的。
二、 Stream数据的读写。
 
---- 1. SaveToStream(Stream: TStream );
//将类中的数据写到Stream的当前位置中
---- 2. LoadFromStream(Stream: TStream);
//从当前位置读入Stream里的数据
---- 实际使用时我们基本上只要使用上面两个函数就可以了。
三、 例子
 
---- TStream的继承树图如图1所示(略),实际使用时比较常用的是TFileStream,TMemoryStream,TblobStream,就以这三种流举一例说明具体用法。
---- 创建一个窗体Form1,放置三个按钮btnRead,btnInvert,btnSave和一个文件打开对话框OpenDialog1以及数据控件DataSource1,Table1,test.
---- 使用Dephi提供的Database Desktop创建一个表test,表里有一个字段域Image,数据库文件名存为test.db。在窗体上放置一个TDatabase控件dbTest,一个TTable控件Table1,一个DataSource控件DataSource1,一个TDBNavigator控件DBNavigator1。将dbTest与刚才Desktop创建的数据库相连,Table1的TableName属性设为test.db,DataSource1的DataSet属性设为Table1,DBNavigator1的DataSource属性设为DataSource1,VisibleButtons属性前四个设为TRUE。此外,将dbtest的Connected设为TRUE,Table1的Active属性设为TRUE,使得数据库一开始就处于打开状态。
---- 事件代码编写如下:
---- 1. btnRead的Click事件,这里演示了TFileStream的用法。
var
MS: TFileStream;
begin
if OpenDialog1.Execute then
begin
MS:=TFileStream.Create
(OpenDialog1.FileName, fmOpenRead);
Image1.Picture.Bitmap.LoadFromStream(MS);
MS.Free;
end;
end;
 
---- 2. btnInvert的Click事件,这里演示了TMemoryStream的用法。其中使用了Invert函数,这是一个简单的将图象反色的函数(仅对真彩图象有效),它返回一个指向处理过的图象数据块的指针。
var
M
S: TMemoryStream;
pImage: pointer;
begin
MS:=TMemoryStream.create;
Image1.Picture.Bitmap.SaveToStream(MS);
MS.Position:=0;
pImage:=Invert(MS.Memory, MS.size);
//Memory属性是指向实际内存块的指针
MS.Write(pImage^,MS.size);
MS.Position:=0;
//上一行代码使指针移到了Stream末尾,所以要复位
Image1.Picture.Bitmap.LoadFromStream(MS);
FreeMem(pImage);
MS.Free;
end;

Invert函数如下:
function TForm1.Invert
(pImage: pointer;
size: Integer): pointer;
var
pData, pMem: PChar;
i: Integer;
begin
pMem:=AllocMem(size);
CopyMemory(pMem,pImage,size);
pData:=pMem+54;
for i:=0 to size-54-1do
begin
pData^:=Char(not integer(pData^));
pData:=pData+1;
end;
Result:=pMem;
end;
 
---- 1. btnSave的Click事件,这里演示了TMemoryStream的另一种用法,将Stream中的数据写到数据库中去。
var
MS: TMemoryStream;
begin
MS:=TMemoryStream.create;
Image1.Picture.Bitmap.SaveToStream(MS);
MS.Position:=0;
Table1.Append;

//在数据库中添加一条记录
TBlobField(Table1.FieldbyName
('image')).LoadFromStream(MS);
Table1.Post;
//将所作的更新写入数据库
end;
 
---- 4. DBNavigator1的Click事件,这里演示了TBlobStream的用法,使用了和写入时不同的方法来读出数据库的图象数据。
var
MS: TStream;
begin
with Table1do
MS:=CreateBlobStream
(FieldbyName('image'),bmRead);
Image1.Picture.Bitmap.
LoadFromStream(MS);
MS.Free;
end;
 
我一直使用BCB就给你个BCB中流的使用方法,一样适用DELPHI。
CBUILDER中相关流对象的讨论
陈俊明 整理
第一章 概述
在CBUILDER中,存在以下几种流对象:
TFileStream
TMemoryStream
TStringStream
TWinSocketStream
TBlobStream
TOleStream
TClientBlobStream
TResourceStream

下面是以上各类的继承关系
TObject
|
TStream
|
+---------------------------+---------------------------+--------------------+-------------------+------------+
| | | | | |
THandleStream TCustomMemoryStream TWinsocketStream TBlobStream TOleStream TStringStream
| |
TFileStream TMemoryStream
|
+-------------------------------------------+
| |
TClientBlobStream TResourceStream

第二章 流对象的属性及方法简介
关于各属性和方法的详细语法请见CBUILDER的帮助
一. TStream介绍
属性
Position:当前位置指针
Size:流的大小,单位为字节
方法
CopyFrom:从一个流往另一个流拷贝数据
Read:从流中读取一定字节的数据到缓冲区,返回读取的字节数
ReadBuffer:从流中读取一定字节的数据到缓冲区,如不正确则异常
ReadComponent:从流中取出一个组件
ReadComponentRes:以Windows的资源文件格式从流中读取一组件
Seek:定位流的当前位置指针
SetSize:设置流的大小。
Write:从缓冲区中将一定字节的数据写入到流中,返回写入的字节数
WriteBuffer:从缓冲区中将一定字节的数据写入到流中,失败则异常
WriteComponent:将一组件写入到流中
WriteComponentRes:将一组件以Windows资源文件的格式写入到流中
注意:不能直接建立一个TStream类型的流对象
二. THandleStream介绍
属性
Handle:流对象要读写的通迅资源的句柄
Size:句柄所标识的资源的大小,单位为字节
方法
Read:从流中读数据到缓冲区中
Seek:设置流的当前位置
SetSize:设置流的大小,不成功则返回一个异常
THandleStream:通过一个打开的句柄建立一个句柄流对象
Write:将数据从缓冲区中写入到流
可以使用THandleStream流对象来存取如文件、套接字、命名管道、邮槽等打开了句柄的通迅资源。下面是一个使用句柄流对象进行文件操作的片段代码:
//////////////////////////////////////////////////////////////////////////////////////////////
////将c:/config.sys文件中的内容读入到一个文本框中
int fileHandle;
THandleStream *fileStream;

fileHandle = FileOpen(“c://config.sys”,fmOpenRead);
if(fileHandle == -1) return ;
//打开文件出错
fileStream = new THandleStream(fileHandle);

char buffer[10001];
unsigned long bufferSize;
do
{
bufferSize = fileStream->Read(buffer, 10000);
if (bufferSize > 0 )
{
buffer[bufferSize] = 0;
Memo1->Text += buffer;
}
}while( bufferSize == 10000 );

delete fileStream;
FileClose(fileHandle);
//请注意一定要先注销流对象才能关闭句柄

三. TCustomMemoryStream介绍
属性
Memory:指向内存流对象的实际内存的指针,可用该指针直接访问内存流的内存
方法
Read:从流中读数据到缓冲区中
SaveToFile:将内存流中的数据保存到文件中
SaveToStream:将内存流中的数据保存到其它流对象中
Seek:设置流对象的当前位置
SetPointer:设置与内存流对象相关联的内存池
注意:该类为纯虚类,不能直接建立其对象。应使用TMemoryStream或是TResourceStream。
四. TWinSocketStream介绍
属性
TimeOut:设置在读或写Socket时的超时值,单位:毫秒
方法
Read:从Socket中读取指定字节的数据到缓冲区中,返回实际读取的字节数
Seek:没有意义
TWinSocketStream:根据指定的Socket句柄和超时时间建立一个Socket流对象
WaitForData:确认是否可以通过Socket连接来发送或接收数据了。
Write:通过Socket连接发送缓冲区中指定字节的数据
TWinSocketStream流对象用来在阻塞方式的Socket连接中发送和接收数据,从而避免一般情况下的挂起现象。下面是一个用TWinSocketStream进行收发数据的代码片段:
/////////////////////////////////////////////////////////////////////////////////////////////////////
//在一单独的线程中通过阻塞式Socket连接发送数据
void __fastcall TMyClientThread::Execute()
{
TWinSocketStream *pStream = new TWinSocketStream(ClientSocket1->Socket, 60000);
try
{
while (!Terminated &&
ClientSocket1->Active)
{
try
{
char buffer[10];
GetNextRequest(buffer);
// GetNextRequest must be a thread-safe method
// write the request to the server
pStream->Write(buffer, strlen(buffer) + 1);
// continue the communication (eg read a response from the server)
...
}
catch (Exception &E)
{
if (!E.ClassNameIs("EAbort"))
//you must write HandleThreadException
Synchronize(HandleThreadException());
}
}
}
__finally
{
delete pStream;
}
}

五. TBlobStream介绍
方法
Read:读取数据到缓冲区中
Seek:定位流的当前位置
TBlobStream:根据一个TBlobField字段建立一个流对象
Truncate:从当前位置截短流对象
Write:将缓冲区中的数据写入到流对象中
TBlobStream流对象只用于对TblobField进行操作,注意,当改变了数据集对象的当前记录时,要重新建立TBlobStream对象并在使用完后将之删除。
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//读取Blob字段的数据
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int MemSize;
char *Buffer;
TBlobStream *Stream;
if (!Query1->Eof)
Query1->Next();
Stream = new TBlobStream((TBlobField *)Query1->FieldByName("Notes"), bmRead);
try
{
MemSize = Stream->Size + 1;
// add one for null terminator
Buffer = new char[MemSize];
// Allocate the memory.
try
{
Stream->Read(Buffer, MemSize);
//Read Notes field into buffer.
Memo1->SetTextBuf(Buffer);
// Display the buffer's contents.
}
catch (...)
{
delete Buffer;
throw;
}
delete Buffer;
}
catch (...)
{
 
我在用BCB5做多层结构系统时,我在Server端加入了一个取得服务器IP地址的方法:GetServerIP它的参数是vIP:Variant *,IN方式,并在服务端实现了这个方法,
加入的代码如下:
*vIP="192.168.0.01";最后我注册成功。
可是在我开发客户端程序时,我用TSocketConnection
当取得它的服务时我是这样做的:
Variant* vip;
SocketConnection1->AppServer.GetServerIP(vip);
Edit1->Tex=vip;
可 是我在运行程序时出错,没有编译通过。
它说getserverIP不是variant的成员
getserverIP is not a memober of variant
请问?
我该如何去调用这个方法呢?
请各位大侠多多指教?
小生的QQ:65466700(24小时在线恭候)
MAIL: alongsun@sina.com
 

Similar threads

D
回复
0
查看
911
DelphiTeacher的专栏
D
D
回复
0
查看
868
DelphiTeacher的专栏
D
D
回复
0
查看
840
DelphiTeacher的专栏
D
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
后退
顶部