Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中读取mbox文件#_C#_Email_Mime_Mbox - Fatal编程技术网

C# 在C中读取mbox文件#

C# 在C中读取mbox文件#,c#,email,mime,mbox,C#,Email,Mime,Mbox,我们的一名员工丢失了他的邮箱,但幸运的是他有一封mbox格式的邮件。我需要以某种方式获取mbox文件中的所有消息,并将它们喷射到我们的技术支持数据库中(因为它是一个自定义工具,没有可用的导入工具) 我发现它可以分解一条消息,但不允许您在mbox文件中遍历一堆消息 有没有人知道一个不需要学习RFC就可以编写出来的语法分析器呢?我不知道任何语法分析器,但是mbox确实是一种非常简单的格式。一封新的电子邮件以“From”(From+空格)开头,每封邮件的末尾都会附加一个空行。如果在电子邮件本身的行首出

我们的一名员工丢失了他的邮箱,但幸运的是他有一封mbox格式的邮件。我需要以某种方式获取mbox文件中的所有消息,并将它们喷射到我们的技术支持数据库中(因为它是一个自定义工具,没有可用的导入工具)

我发现它可以分解一条消息,但不允许您在mbox文件中遍历一堆消息


有没有人知道一个不需要学习RFC就可以编写出来的语法分析器呢?

我不知道任何语法分析器,但是mbox确实是一种非常简单的格式。一封新的电子邮件以“From”(From+空格)开头,每封邮件的末尾都会附加一个空行。如果在电子邮件本身的行首出现“From”,则会将其引用(通过在“>”前面加上前缀)


另请参见。

如果您可以扩展到使用Python,则标准库中有。遗憾的是,我找不到任何适用于.NET的语法分析器。

我正在用C语言编写一个名为MIME&mbox的语法分析器

它基于我以前编写的MIME和mbox解析器(例如),速度非常快(可以在大约1秒内解析1.2GB mbox文件中的每条消息)

我还没有测试MimeKit的性能,但我在C中使用了许多与我在C中使用的相同的技术。我怀疑它会比我的C实现慢,但由于瓶颈是I/O,而且MimeKit是为了像GMime一样进行最佳(4k)读取而编写的,所以它们应该非常接近

您发现当前方法速度慢的原因(StreamReader.ReadLine(),组合文本,然后将其传递给SharpMimeTools)是因为以下原因:

  • ReadLine()不是从文件中读取数据的最佳方式。虽然我确信StreamReader()执行内部缓冲,但它需要执行以下步骤:

    A) 将从文件读取的字节块转换为unicode(这需要迭代从磁盘读取的字节[]中的字节,以将从流读取的字节转换为unicode字符[])

    B) 然后它需要迭代其内部字符[],将每个字符复制到StringBuilder中,直到找到“\n”

    因此,在这里,只要读取行,就可以在mbox输入流上至少传递2次。更不用说所有正在进行的内存分配了

  • 然后你把你读到的所有行合并成一个大字符串。这需要对输入进行另一次传递(大概是将从ReadLine()读取的每个字符串中的每个字符复制到StringBuilder中?)

    我们现在对输入文本进行了3次迭代,甚至还没有进行任何解析

  • 现在你把你的超级字符串交给SharpMimeTools,它使用一个SharpMimeMessageStream,它。。。(/facepalm)是一个基于ReadLine()的解析器,位于另一个执行字符集转换的StreamReader之上。在解析任何内容之前,需要进行5次迭代。SharpMimeMessageStream还有一种方法,可以在发现读线()读得太远时“撤消”读线()。因此,我们有理由假设他至少扫描了其中一些线条两次。更不用说所有正在进行的字符串分配。。。啊

  • 对于每个标题,一旦SharpMimeTools有了行缓冲区,它将拆分为字段和值。这是另一个通行证。到目前为止,我们已经通过了6次

  • 然后,SharpMimeTools使用string.Split()(这很好地表明此mime解析器不符合标准)通过在“”上拆分来标记地址头,并通过在“;”上拆分来标记参数化头(如内容类型和内容处置)。这是另一个通行证。(我们现在最多可以通过7次。)

  • 一旦它拆分了这些内容,它将对从string.Split()返回的每个字符串运行一个正则表达式匹配,然后每个rfc2047编码的单词标记执行更多正则表达式传递,最后再对编码的单词字符集和负载组件执行另一次传递。我们所说的是,到目前为止,至少有9到10次传递了大部分输入

  • 我不再继续我的考试了,因为它已经是GMime和MimeKit所需要的两倍多的通过次数了,而且我知道我的解析器可以优化,至少比它们少通过一次

    另外,作为旁注,任何解析字符串而不是字节[](或sbyte[])的MIME解析器都不会很好。电子邮件的问题在于,太多的邮件客户端/脚本等会在邮件头和邮件正文中发送未声明的8位文本。unicode字符串解析器如何处理这个问题?提示:它不能

    using (var stream = File.OpenRead ("Inbox.mbox")) {
        var parser = new MimeParser (stream, MimeFormat.Mbox);
        while (!parser.IsEndOfStream) {
            var message = parser.ParseMessage ();
    
            // At this point, you can do whatever you want with the message.
            // As an example, you could save it to a separate file based on
            // the message subject:
            message.WriteTo (message.Subject + ".eml");
    
            // You also have the ability to get access to the mbox marker:
            var marker = parser.MboxMarker;
    
            // You can also get the exact byte offset in the stream where the
            // mbox marker was found:
            var offset = parser.MboxMarkerOffset;
        }
    }
    
    2013年9月18日更新:我已经让MimeKit达到了可以用来解析mbox文件的地步,并且成功地解决了问题,但它的速度远不及我的C库。这是在iMac上测试的,因此I/O性能不如在我的旧Linux机器上(GMime可以在1秒内解析大小类似的mbox文件):

    正如您所看到的,GMime仍然要快一点,但是我对如何提高MimeKit解析器的性能有一些想法。原来C#的
    fixed
    语句非常昂贵,所以我需要重新使用它们。例如,我昨天剃了大约2-3秒的胡子(如果我没记错的话)

    优化更新:通过替换以下内容,性能又提高了20%:

    while (*inptr != (byte) '\n')
        inptr++;
    
    与:

    优化更新:我最终能够通过切换使用Enum.HasFlag()而改用直接位屏蔽,使MimeKit的速度与GMime一样快

    MimeKit现在可以在3.78秒内解析相同的mbox流

    相比之下,SharpMimeTools需要20多分钟(为了测试这一点,我不得不将电子邮件拆分为单独的文件,因为SharpMimeTools无法解析mbox文件)


    另一个更新:通过代码中的各种其他调整,我将其降到了3.00s平面。

    要读取.mbox文件,可以使用第三方库。 这个图书馆是一个完整的图书馆
    while (*inptr != (byte) '\n')
        inptr++;
    
    do {
        mask = *dword++ ^ 0x0A0A0A0A;
        mask = ((mask - 0x01010101) & (~mask & 0x80808080));
    } while (mask == 0);
    
    inptr = (byte*) (dword - 1);
    while (*inptr != (byte) '\n')
        inptr++;
    
    using(FileStream stream = new FileStream("ExampleMbox.mbox", FileMode.Open, FileAccess.Read))
    {
        using(MboxrdStorageReader reader = new MboxrdStorageReader(stream, false))
        {
            // Start reading messages
            MailMessage message = reader.ReadNextMessage();
    
            // Read all messages in a loop
            while (message != null)
            {
                // Manipulate message - show contents
                Console.WriteLine("Subject: " + message.Subject);
                // Save this message in EML or MSG format
                message.Save(message.Subject + ".eml", SaveOptions.DefaultEml);
                message.Save(message.Subject + ".msg", SaveOptions.DefaultMsgUnicode);
    
                // Get the next message
                message = reader.ReadNextMessage();
            }
        }
    }