【问题标题】:Indy SaveToFile vs SaveToStream and BCCIndy SaveToFile vs SaveToStream 和 BCC
【发布时间】:2013-10-28 01:01:03
【问题描述】:

我了解 Indy 开发人员选择在使用 SaveToStream 时去除消息的 BCC 标头,因为流可以是基于套接字的。但是,如果我想将消息实际保存到流中以供进一步处理怎么办?此外,如果我想剥离末尾添加的 CRLF.CRLF 怎么办?这方面的示例是将消息保存到 MBOX 类型的文件。这当然不能直接完成。

所以我现在的做法是一团糟:

// Writing to MBOX
// Save to temp file
IdMsg->SaveToFile("filenamewrite.tmp",false);

// Make file shorter by 5 trailing bytes
boost::scoped_ptr<TFileStream> fs(new TFileStream("filenamewrite.tmp", fmOpenWrite | fmShareDenyWrite));
fs->Size = fs->Size-5;
FlushFileBuffers(reinterpret_cast<void *>(fs->Handle));

// Now this file can be copied to another stream with "mbox"-like file.

对于加载:

// Reading from MBOX
boost::scoped_ptr<TFileStream> fs(new TFileStream("mboxfile", fmOpenRead | fmShareDenyWrite));
AnsiString Data;
Data.SetLength(12345);
fs->Read(const_cast<void *>(Data.data()), Data.Length());
boost::scoped_ptr<TStringList> sl(new TStringList);
sl->Text = Data;
sl->SaveToFile("filenameread.tmp");
IdMsg->LoadFromFile("filenameread.tmp");

当然,这样做的效率极低,完全没有必要。如果可以直接保存到流中,那将是两行代码,而不是上面的混乱。

有没有更好的方法?添加一个重载的SaveToStream 以允许删除 CRLF.CRLF 并在 Indy 中保存 BCC 标头如何?从 MBOX 加载消息时,LoadFromStream 也类似,因此可以直接从流中加载,无需添加尾随 CRLF.CRLF。

【问题讨论】:

    标签: delphi stream c++builder indy


    【解决方案1】:

    TIdMessage 仅在调用 TIdMessage.SaveToFile() 时写入 BCC 标头。如果不更改 Indy 的源代码或使用 hack 类,就无法让 TIdMessage.SaveToStream() 写入 BCC 标头。但是,您可以手动将 BCC 数据存储在 TIdMessage.ExtraHeaders 属性中,以便 SaveToStream() 可以写入它。

    至于处理多余的点等,那是因为加载/写入实际上是由TIdMessageClient 完成的,它没有流的概念,也没有任何除 POP3/SMTP 之外的任何源/目标的概念。这是 Indy 当前架构中的硬编码限制,将在 Indy 11 中解决。同时,有使用 TIdIOHandlerStreamMsg 类的解决方法。

    试试这个:

    IdMsg->ExtraHeaders->Values["Bcc"] = EncodeAddress(IdMsg->BCCList, 'B', "utf-8");
    boost::scoped_ptr<TIdMessageClient> msgClient(new TIdMessageClient(NULL));
    boost::scoped_ptr<TIdIOHandlerStreamMsg> io(new TIdIOHandlerStreamMsg(NULL, NULL, Target Stream Goes Here);
    io->UnescapeLines = true; // <-- this is the key step!
    io->FreeStreams = false;
    msgClient->IOHandler = io.get();
    msgClient->SendMsg(IdMsg, false);
    

    IdMsg->Clear();
    boost::scoped_ptr<TIdMessageClient> msgClient(new TIdMessageClient(NULL));
    boost::scoped_ptr<TIdIOHandlerStreamMsg> io(new TIdIOHandlerStreamMsg(NULL, Source Stream Goes Here, NULL);
    io->EscapeLines = true; // <-- this is the key step!
    io->FreeStreams = false;
    msgClient->IOHandler = io.get();
    io->Open();
    msgClient->ProcessMessage(IdMsg, false);
    

    UnescapeLines=true 导致TIdIOHandlerStreamMsg 在保存TIdMessage 时静默撤消TIdMessageClient 写入的额外数据。

    EscapeLines=true 导致 TIdIOHandlerStreamMsg 添加额外的数据,TIdMessageClient 在加载 TIdMessage 时期望解析。

    【讨论】:

    • 我知道这是一种解决方法。但是把上面的变成内置函数怎么样?
    • 因为它需要更改界面,我还没有准备好。
    • 仅供参考,我最终为TIdMessage 创建了一个单独的class helper 以添加重载的LoadFrom...()SaveTo...() 方法来处理点透明度问题,但它没有已经签到了。
    • 谢谢!会调查一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 2021-05-03
    • 2021-07-31
    • 2021-03-05
    相关资源
    最近更新 更多