怎么把组件里的内容转成流,需要时再将流转成原来的内容。(50分)

  • 主题发起人 易名烦
  • 开始时间
TMD,最讨厌INDY的东西。
 
哪我用哪个的呢?
给想想吧![:D]
 
继续UP!
 
beta:
你用的是D6吧?
 
// tidmessageparts!是INDY的东东!
它总有一些属性是你需要的吧,你需要的是那几个
属性?把他们列举出来:按照名字——类型的格式

我现在在宿舍,网速太慢,等我待会儿到科协那边去
那边网速快。少等一下。
 
其它的都是字符。
只有这个东西不是。它存的主要是一邮件的全部内容(包括附件)。
procedure TForm1.Button4Click(Sender: TObject);
var
messagepart:tmemorystream;
begin
if not ad1.Active then
ad1.Open;
msg.Clear; //msg是TIDMESSAGE!也是INDY的组件
idpop31.Retrieve(strtoint(edit1.Text),msg);
ad1.Append;
ad1.FieldByName('FromName').AsString:=msg.From.Text;
ad1.FieldByName('FromAddress').AsString:=msg.From.Address;
ad1.FieldByName('ToAddress').AsString:=msg.Recipients.EMailAddresses;
ad1.FieldByName('subject').AsString:=msg.Subject;
ad1.FieldByName('date').AsDateTime:=msg.Date;
messagepart:=tmemorystream.Create;
messagepart.WriteComponent(tcomponent(msg.MessageParts));
memo1.Lines:=tmemostring(msg.MessageParts.Items[1].);
messagepart.Seek(0,sofrombeginning);
showmessage(inttostr((messagepart.Size)));
Tblobfield(ad1.FieldByName('MessageParts')).LoadFromStream(messagepart);
ad1.Post;
end;
 
我知道,你的关键问题是 MessageParts 的保存,现在我们看看这个类的结构:
它是一个 TMessagePart 的列表,于是问题转化为 TMessagePart 的结构:
通过观察其 Assign 方法知,关键在于其三个 Published 属性:
ContentTransfer,ContentType,ExtraHeaders
其中,前两者为字符串类型,很容易解决,关键是后者,再看看:
它是一个 TIdHeaderList 类型的,而这个类型又继承自 TStringList
呵呵,又一个熟悉的类型,但是,它还新增了几个属性:
FNameValueSeparator: string;
FCaseSensitive: Boolean;
FUnfoldLines: Boolean;
FFoldLines: Boolean;
FFoldLinesLength: Integer;
可以看到,现在所有的属性都是已知的简单类型了,问题基本上理顺了。

写出代码如下:(主要是体力活[:)])我选择了用 TMemoryStream 类型

procedure SaveMessageParts(mp: TMessageParts; Stream: TMemoryStream);

procedure WriteString(Str: string);
var
Size: Integer;
begin
Size := SizeOf(Str);
// 写入字符串长度,便于读取
Stream.Write(Size, SizeOf(Size));
// 写入字符串
Stream.Write(Str[1], Size);
end;

procedure WriteInteger(Int: Integer);
begin
Stream.Write(Int, SizeOf(Int));
end;

var
i: Integer;
begin
// 由于 TMessageParts 是一个列表,循环保存其中每一个 TMessagePart
for i := 0 to mp.Count - 1 do
begin
// 保存 TMessagePart 的前两个 Published 属性,字符串
WriteString(mp.ContentTransfer);
WriteString(mp.ContentType);
// 保存 TMessagePart 的最后一个 Published 属性 ExtraHeaders
// 首先保存其 StringList,将整个 StringList 作为一个 Text 字符串
WriteString(mp.ExtraHeaders.Text);
// 接着保存 ExtraHeaders 中剩下的几个新增属性
WriteString(mp.ExtraHeaders.FNameValueSeparator);
WriteInteger(Ord(mp.ExtraHeaders.FCaseSensitive)); // 将布尔型看作整型
WriteInteger(Ord(mp.ExtraHeaders.FUnfoldLines)); // 将布尔型看作整型
WriteInteger(Ord(mp.ExtraHeaders.FFoldLines)); // 将布尔型看作整型
WriteInteger(FFoldLinesLength);
end;
Stream.Position := 0;
end;

基本上就是这个样子了,看明白了吗?读出部分你自己试一试吧,要是不行我再帮你写
记住要以相同的顺序读出来。读字符串的话,要先读出其长度(我就是这样写的)。
 
procedure MessagePartstostream(mp: TIDMessageParts; Stream: TMemoryStream);
procedure WriteString(Str: string; Stream: TMemoryStream);
var
Size: Integer;
begin
Size := SizeOf(Str); // 写入字符串长度,便于读取
Stream.Write(Size, SizeOf(Size)); // 写入字符串
Stream.Write(Str[1], Size);
end;

procedure WriteInteger(Int: Integer; Stream: TMemoryStream);
begin
Stream.Write(Int, SizeOf(Int));
end;

var
i: Integer;
begin
// 由于 TMessageParts 是一个列表,循环保存其中每一个 TMessagePart
for i := 0 to mp.Count - 1 do
begin
// 保存 TMessagePart 的前两个 Published 属性,字符串
WriteString(mp[0].ContentTransfer,stream);
WriteString(mp[0].ContentType,stream);
// 保存 TMessagePart 的最后一个 Published 属性 ExtraHeaders
// 首先保存其 StringList,将整个 StringList 作为一个 Text 字符串
WriteString(mp[0].ExtraHeaders.values,stream); // 接着保存 ExtraHeaders 中剩下的几个新增属性

WriteString(mp[0].ExtraHeaders.FNameValueSeparator,stream);
WriteInteger(Ord(mp[0].ExtraHeaders.FCaseSensitive),stream); // 将布尔型看作整型
WriteInteger(Ord(mp[0].ExtraHeaders.FUnfoldLines),stream); // 将布尔型看作整型
WriteInteger(Ord(mp[0].ExtraHeaders.FFoldLines),stream); // 将布尔型看作整型
WriteInteger(mp[0].ExtraHeaders.FFoldLinesLength,stream);
end;
Stream.Position := 0;
end;
 
把你编译不通过的部分的几个属性的第一字字母:F 去掉
那些是私有属性,不能直接访问,Copy的时候没有注意:)
去掉 F 过后就是相应的公有属性了,可以访问了

另:你加的那几个 Stream 都是不必要的,因为 WriteString
和 WriteInteger 都是定义在 SaveMessageParts 函数内
部的,是它的子函数,子函数当然可以访问父函数的参数
因此可以直接使用 Stream 参数,这样更加简洁:)
当然,你加了也不会错。
 
出错怎么办?内存
 
在什么时候出错?那个部分?
 
没提示出错在哪一行,只是弹出对话框,好象什么出错在0X005451,不能READ之类的.
 
至少你可以判断在哪个模块出的错啊,保存部分还是读取部分?

 
保存啊!
写STREAM还没完就出错!
 
你怎么全部是用的 mp[0] 啊,我不是都改成 mp 了吗:)

你单步跟踪一下,看看在写哪行的时候出错的?
 
改了,现在跟踪!
 
先用一个简单的试试,另外类型转换时,是不是转换运行时类,不要转换成基类。
 
procedure MessagePartstostream(mp: TIDMessageParts; Stream: TMemoryStream);
procedure WriteString(Str: string; Stream: TMemoryStream);
var
Size: Integer;
begin
Size := SizeOf(Str); // 写入字符串长度,便于读取
Stream.Write(Size, SizeOf(Size)); // 写入字符串
[red]Stream.Write(Str[1], Size);[/red]
end;

procedure WriteInteger(Int: Integer; Stream: TMemoryStream);
begin
Stream.Write(Int, SizeOf(Int));
end;

var
i: Integer;
begin
// 由于 TMessageParts 是一个列表,循环保存其中每一个 TMessagePart
for i := 0 to mp.Count - 1 do
..................................
end;
红色部份出错!
 
还没有搞定?这么难呀?
我的信箱都快被你们搞炸了!
 
顶部