当前位置: 首页 > 编程语言 > C#

在C#中阅读mbox文件分享

时间:2023-04-11 01:29:03 C#

在C#中阅读mbox文件我们的一位工作人员丢失了他的邮箱,但幸运的是他转发了mbox格式的邮件。我需要以某种方式获取mbox文件中的所有消息并将它们喷射到我们的技术支持数据库中(因为它是一个自定义工具,所以没有可用的导入工具)。我发现SharpMimeTools会分解一条消息,但不允许您遍历mbox文件中的一堆消息。有谁知道无需学习RFC即可编写一个像样的解析器?我不知道有什么解析器,但mbox实际上是一种非常简单的格式。新消息以“发件人”(发件人+空格)开头的行开始,每个消息行的末尾附加一个空行。如果“发件人”出现在电子邮件本身一行的开头,它将被引出(通过添加“>”)。另请参阅有关该主题的维基百科条目。我在C#中使用MIME和mbox解析器调用MimeKit。它基于我编写的早期MIME和mbox解析器(例如GMime),它们非常快(可以在大约1秒内解析1.2GBmbox文件中的每条消息)。我没有测试MimeKit的性能,但我在C中使用了很多与在C中使用的相同的技术。我怀疑它会比我的C实现慢,但由于瓶颈是I/O,而MimeKit是为了做optimal(4k)读起来像GMime,它们应该非常接近。您发现当前方法缓慢的原因(StreamReader.ReadLine(),组合文本,然后将其传递给SharpMimeTools)是由于以下原因:StreamReader.ReadLine()不是从中读取数据的最佳方式一份文件。虽然我确定StreamReader()会进行内部缓冲,但它需要执行以下步骤:A)将从文件读取的字节块转换为unicode(这需要迭代从磁盘读取的byte[]中的字节以进行转换从流中读取的字节被转换为unicodechar[])。B)然后它需要遍历其内部char[],将每个char复制到StringBuilder,直到找到“n”。因此,只有读取行,您至少有2次传递到您的mbox输入流。更不用说正在进行的所有内存分配......然后,将所有读取的行组合成一个字符串。这需要再次传递您的输入(大概是将从ReadLine()读取的每个字符串中的每个字符复制到StringBuilder中?)。我们现在对输入文本进行了3次迭代,我们甚至还没有解析它。现在,您将超字符串交给SharpMimeTools...(/facepalm),它使用SharpMimeMessageStream,这是一个基于ReadLine()的解析器,位于另一个进行字符集转换的StreamReader之上。这甚至可以在任何事情之前进行5次迭代。如果SharpMimeMessageStream发现它读得太远,它还有一种方法可以“撤消”ReadLine()。所以有理由假设他至少扫描了其中一些线两次。更不用说正在进行的所有字符串分配......呃。对于每个标头,一旦SharpMimeTools有了它的行缓冲区,它就会被分成字段和值。那是另一个通行证。到目前为止,我们已经能够通过多达6次。SharpMimeTools然后使用string.Split()(这是一个很好的迹象表明此mime解析器不符合标准)通过拆分','和参数化标头(如Content-Type和Content-Disposition';')来标记化在地址标题上。那是另一个通行证。(我们现在最多7次传递。)一旦它被拆分,它就会对string返回的每个字符串运行正则表达式匹配。在一次传递之前,每个rfc2047编码的单词标记传递更多的正则表达式。到目前为止,我们讨论的主要是至少9或10次传递的输入。我放弃了我的考试,因为它已经比GMime和MimeKit需要的多2倍,而且我知道我的解析器至少可以比它们少优化一次。此外,作为旁注,任何解析字符串而不是byte[](或sbyte[])的MIME解析器都不会很好。电子邮件的问题是许多邮件客户端/脚本/等在野外会在标题和消息文本中发送未声明的8位文本。unicode字符串解析器如何处理这个问题?提示:不能。2013-09-18更新:我已经使用MimeKit来解析mbox文件并成功地解决了这个问题,但它没有我的C库那么快。这是在iMac上测试的,所以I/O性能不如我的旧Linux机器(这是GMime能够在~1s内解析类似大小的mbox文件):[fejj@localhostMimeKit]$mono./mbox-parser.exelarger.mbox在6.16秒内解析了14896条消息。[fejj@localhostMimeKit]$./gmime-mbox-parserlarger.mbox在3.78秒内解析了14896条消息。[fejj@localhostMimeKit]$ls-llarger.mbox-rw-r--r--1fejjstaff1032555628Sep1812:43larger.mbox如你所见,GMime仍然很快,但我有一些想法关于如何提高MimeKit解析器的性能。原来C#的fixed语句开销很大,需要复用。例如,我昨天做的一个简单优化将总时间缩短了大约2-3秒(如果我没记错的话)。优化更新:通过替换将性能提高20%:while(*inptr!=(byte)'n')inptr++;与:做{mask=*dword++^0x0A0A0A0A;掩码=((掩码-0x01010101)&(~掩码&0x80808080));}而(掩码==0);inptr=(byte*)(dword-1);while(*inptr!=(byte)'n')inptr++;优化更新:我终于可以通过切换到使用Enum.HasFlag()并使用直接位掩码,最终使MimeKit与GMime一样快。MimeKit现在可以在3.78秒内解析相同的mbox流。相比之下,SharpMimeTools需要20多分钟(为了对此进行测试,我不得不将电子邮件拆分为单独的文件,因为SharpMimeTools无法解析mbox文件)。另一个更新:我通过对代码进行各种其他调整将其降低到3.00s。如果您会使用Python,那么标准库中就有一个。不幸的是,我找不到.NET。以上就是C#学习教程:阅读C#中mbox文件分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处: