【问题标题】:BeanIO InvalidRecordGroupException giving wrong line numberBeanIO InvalidRecordGroupException 给出错误的行号
【发布时间】:2017-09-07 22:03:23
【问题描述】:

我正在使用 BeanIO 来解析一个固定宽度的文本文件。例如,进入我的项目的文件看起来像以下固定宽度的文本:

 CD DummyValue3
 EF DummyValue4 DummyValue5 DummyValue6
 AB DummyValue1 DummyValue2
 ...

在我的映射文件中,我为每个记录 ID(即 AB、CD、EF)声明了一个 record

<record name="dummyRecord" template="AB"
class="com.company.project.DummyRecordClass" minOccurs="0"
maxOccurs="1" />

然后每条记录都有一个template

<template name="AB">
    <field name="recordID" length="3" rid="true" literal="AB"
           lenientPadding="true" minOccurs="0" />
    <field name="value1" length="12" lenientPadding="true"
           minOccurs="1" required="true"/>
    <field name="value2" length="12" lenientPadding="true"
           minOccurs="1" required="true"/>
</template>

因为value1value2 有一个minOccurs = 1 和一个required="true"(是的,我知道这是多余的,但它已经在代码中并且我们有数千个这样的字段)如果我有一个 AB 段。

如果我要将以下文件传递到我的程序中:

 CD DummyValue3
 EF DummyValue4 DummyValue5 DummyValue6
 AB DummyValue1

我收到以下 InvalidRecordGroupException:

org.beanio.InvalidRecordGroupException: Invalid 'ediMessage' record group at line 1

但是,由于缺少的字段实际上位于第 3 行,当您有 500-600 行数据进入应用程序时,调试起来可能会非常痛苦。

有没有办法让 beanIO 输出正确的行号,或者在缺少必填字段时输出 templatefield 值?

【问题讨论】:

    标签: java parsing bean-io


    【解决方案1】:

    我通过扩展org.beanio.BeanReaderErrorHandlerSupport 来使用org.beanio.BeanReaderErrorHandler 的自定义实现来创建LoggingErrorHandler

    import org.beanio.BeanReaderErrorHandlerSupport;
    import org.beanio.BeanReaderException;
    import org.beanio.InvalidRecordException;
    import org.beanio.MalformedRecordException;
    import org.beanio.RecordContext;
    import org.beanio.UnexpectedRecordException;
    import org.beanio.UnidentifiedRecordException;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * A BeanIO {@code BeanReaderErrorHandler} that logs the error messages.
     *
     * @author Nico Schlebusch
     */
    public class LoggingBeanReaderErrorHandler extends BeanReaderErrorHandlerSupport {
    
      private static final Logger LOGGER = LoggerFactory.getLogger(LoggingBeanReaderErrorHandler.class);
    
      /**
       * Creates a new instance of {@code LoggingBeanReaderErrorHandler}.
       */
      public LoggingBeanReaderErrorHandler() {
      }
    
      /**
       * {@inheritDoc}
       *
       * @see org.beanio.BeanReaderErrorHandlerSupport#invalidRecord(org.beanio.InvalidRecordException)
       */
      @Override
      public void invalidRecord(final InvalidRecordException ex) throws BeanReaderException {
    
        LOGGER.error("{}", createErrorMessage(ex));
      }
    
      /**
       * {@inheritDoc}
       *
       * @see org.beanio.BeanReaderErrorHandlerSupport#unexpectedRecord(org.beanio.UnexpectedRecordException)
       */
      @Override
      public void unexpectedRecord(final UnexpectedRecordException ex) throws BeanReaderException {
    
        LOGGER.error("{}", createErrorMessage(ex));
      }
    
      /**
       * {@inheritDoc}
       *
       * @see org.beanio.BeanReaderErrorHandlerSupport#unidentifiedRecord(org.beanio.UnidentifiedRecordException)
       */
      @Override
      public void unidentifiedRecord(final UnidentifiedRecordException ex) throws BeanReaderException {
    
        LOGGER.error("{}", createErrorMessage(ex));
      }
    
      /**
       * {@inheritDoc}
       *
       * @see org.beanio.BeanReaderErrorHandlerSupport#malformedRecord(org.beanio.MalformedRecordException)
       */
      @Override
      public void malformedRecord(final MalformedRecordException ex) throws BeanReaderException {
    
        LOGGER.error("{}", createErrorMessage(ex));
      }
    
      /**
       * {@inheritDoc}
       *
       * @see org.beanio.BeanReaderErrorHandlerSupport#fatalError(org.beanio.BeanReaderException)
       */
      @Override
      public void fatalError(final BeanReaderException ex) throws BeanReaderException {
    
        LOGGER.error("{}", createErrorMessage(ex));
      }
    
      /**
       * Creates an error message using the exception to get the RecordContext from which a meaningful error
       * message can be constructed.
       *
       * @param ex the exception containing the error information.
       *
       * @return a string describing the error(s).
       */
      protected String createErrorMessage(final BeanReaderException ex) {
    
        final String message = ex.getMessage();
        final StringBuilder errorMessage = new StringBuilder(message.length() * 5);
    
        // if a bean object is mapped to a record group,
        // the exception may contain more than one record
        for (int i = 0, j = ex.getRecordCount(); i < j; i++) {
          final RecordContext recordContext = ex.getRecordContext(i);
          final String recordName = recordContext.getRecordName();
          final String text = recordContext.getRecordText();
          errorMessage.append(String.format("%s: %s%n", message, text));
    
          if (recordContext.hasRecordErrors()) {
            for (final String error : recordContext.getRecordErrors()) {
              errorMessage.append(String.format("Record '%s' - %s%n", recordName, error));
            }
          }
          if (recordContext.hasFieldErrors()) {
            for (final String field : recordContext.getFieldErrors().keySet()) {
              for (final String error : recordContext.getFieldErrors(field)) {
                errorMessage.append(String.format("Field '%s' - %s%n", field, error));
              }
            }
          }
        }
    
        return errorMessage.toString();
      }
    
    }
    

    您可以修改createErrorMessage() 方法以仅保留您要查找的信息。

    当然,您可以使用这些信息做很多其他事情,例如将其写入文件、通过电子邮件发送等。请参阅文档的 BeanReaderErrorHandler 部分以了解替代方案。

    然后您必须使用您的 BeanReader 实例注册错误处理程序:

    BeanReader beanReader = ....
    beanReader.setErrorHandler(errorHandler);
    

    这应该会输出有关错误所在位置的更多信息。

    【讨论】:

      猜你喜欢
      • 2013-06-08
      • 1970-01-01
      • 2020-12-11
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 2018-11-29
      • 1970-01-01
      • 2017-01-11
      相关资源
      最近更新 更多