java - MIME4J 中基于事件的解析 - 如何从 InputStream 填充新消息?

标签 java parsing mapreduce mime4j

我正在使用 MIME4J 从电子邮件堆栈转储中读取 MIME 事件。我正在尝试读取由 START_MESSAGE 和 END_MESSAGE header 定义的给定消息事件作为整个事件,因为我最终会将进程移动到分布式文件系统,并且需要规划文件分割边界遍历。

对于mime4j中基于事件的解析,需要一个ContentHandler接口(interface),并且解析器从它调用方法,这需要为其设置处理程序。我已经尝试了另一个 SO 答案中的示例处理程序,该处理程序扩展了 mime4j 打包的 SimpleContentHandler,但该处理程序实际上只解析 header 。

我正在尝试构建自定义 ContentHandler 类以将完整消息收集为一个事件。然后,我需要将事件放在临时对象中,以便我可以解析 header 、它们的字段以及其中的字段内容。最终目标是使这种行为适应 MapReduce,因此有必要处理电子邮件的一部分位于一个文件分割中,而另一部分位于不同文件分割中的情况。

对于我的自定义 ContentHandler,我已经做到了:

public class CustomContentHandler extends AbstractContentHandler {}

对于主要内容,我正在使用:

    public class Reader 
    {
     public static void main( String[] args ) throws FileNotFoundException, IOException,
     MimeException
    {

   QaContentHandler handler = new CustomContentHandler();
   MimeConfig config = new MimeConfig();
   MimeStreamParser parser = new MimeStreamParser(config);
   InputStream stream = new FileInputStream("/home/javadev1/lib/INBOX");

   parser.setContentHandler(handler);
   try 
   {
    do 
    {   
   parser.parse(stream);
   }
    while (stream.read() != -1);
       } 
   finally 
    {
           stream.close();
       }
    }

    }

因此,任何有关如何在处理程序中构建信息的帮助都会非常有帮助。我尝试设置一个新的 MessageImpl,然后使用构建器将已解析的流复制到其中,并且我还尝试从流的解析中构建一个 newMessage,然后在读取 END_MESSAGE header 时打印该消息,但它打印了 null。

我可能也遇到了概念盲点。如果是这样的话,我同意指出这一点。谢谢!

最佳答案

这是适合我的代码摘录。一旦我使用基于状态的解析器发现有趣的消息,我就会切换到 dom 解析器来创建消息对象。

/**
 * check the MessageStream
 * 
 * @param in - the inputstream to check
 * @param id - the id of a message to search for
 * @param encoding - the encoding of the stream e.g. ISO-8859
 * @return - the message with the given id of null if none is found
 * @throws IOException
 * @throws MimeException
 */
public Message checkMessageStream(InputStream in, String id, Charset encoding)
        throws IOException, MimeException {
    // https://james.apache.org/mime4j/usage.html
    String messageString = new String(StreamUtils.getBytes(in));
    messageString = fixMessageString(messageString);
    InputStream instream = new ByteArrayInputStream(
            messageString.getBytes(encoding));
    MimeTokenStream stream = new MimeTokenStream();
    stream.parse(instream);
    for (EntityState state = stream.getState(); state != EntityState.T_END_OF_STREAM; state = stream
            .next()) {
        switch (state) {
        case T_BODY:
            if (debug) {
                System.out.println("Body detected, contents = "
                        + stream.getInputStream() + ", header data = "
                        + stream.getBodyDescriptor());
            }
            break;
        case T_FIELD:
            Field field = stream.getField();
            if (debug) {
                System.out.println("Header field detected: " + stream.getField());
            }
            if (field.getName().toLowerCase().equals("message-id")) {
                // System.out.println("id: " + field.getBody() + "=" + id + "?");
                if (field.getBody().equals("<" + id + ">")) {
                    InputStream messageStream = new ByteArrayInputStream(
                            messageString.getBytes(encoding));
                    Message message = MessageServiceFactory.newInstance()
                            .newMessageBuilder().parseMessage(messageStream);
                    return message;
                } else {
                    return null;
                }
            }

            break;
        case T_START_MULTIPART:
            if (debug) {
                System.out.println("Multipart message detexted," + " header data = "
                        + stream.getBodyDescriptor());
            }
            break;
        }
    }
    return null;
}

关于java - MIME4J 中基于事件的解析 - 如何从 InputStream 填充新消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21170222/

相关文章:

c++ - 自动将代码插入现有 C++ 代码的最简单方法是什么?

parsing - 如果从文件中读取,Parsec 将失败且没有错误

java - TotalOrderPartitioner 和分区文件

java - 使用itext在pdf中显示总页数错误

java - Maven 中的混合 Clojure 和 Java 项目

java - 如何通过java执行cmd命令

parsing - 使用 AWK(或 SED)获取字符串之间的文本 - 包括 START 字符串但排除 END 字符串

java - 删除字符串中最后一个已知单词

hadoop - HBase completebulkload 返回异常

hadoop - Reducer迭代context.write