平面文件解析:当某些字段包含定界符时

时间:2019-06-07 15:30:29

标签: java parsing spring-batch flat-file

我有一个spring-batch应用程序,它使用该读取器读取文件:

<bean id="tradeItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    <property name="resource">
        <bean class="org.springframework.core.io.FileSystemResource">
            <constructor-arg value="${input.file.path}/#{jobExecutionContext['trades']}" type="java.lang.String"/>
        </bean>
    </property>
    <property name="linesToSkip" value="1" />
    <property name="lineMapper">
        <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
            <!-- split it -->
            <property name="lineTokenizer">
                <bean
                    class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                    <beans:property name="strict" value="false" />
                    <beans:property name="includedFields" value="0,2,3,6" />
                    <property name="names"
                        value="field0,field2,field3,field6" />
                </bean>
            </property>
            <property name="fieldSetMapper">
                <bean
                    class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
                    <property name="prototypeBeanName" value="trade" />
                </bean>
            </property>
        </bean>
    </property>
</bean>

这些字段用逗号,分隔,这是要抓住的地方:有些字段看起来像[LON, TGT],由于方括号内的逗号,该行最终被错误地解析。

示例:

输入:Global,,VERIFIED,[LON, TGT],ERerd,3456585,QTR,20190929,20231020

所需的输出:GlobalVERIFIED[LON, TGT]QTR

实际输出:GlobalVERIFIED[LON3456585

我该如何实现?我无法控制输入文件。

EDIT

这不是重复的,因为建议的解决方案不起作用:这里我们没有单个引号字符,但是我们有两个不同的引号,即左括号和右括号。

1 个答案:

答案 0 :(得分:0)

正如卢卡·巴索·里奇(Luca Basso Ricci)解释的那样,我输入的csv无效,但是我仍然要处理它,因为我无法控制它。

因此,我编写了自己的定界行标记器,即只是DelimitedLineTokenizer和重写的isDelimiter()方法,并将其替换为conf文件:

  private boolean isDelimiter(char[] chars, int i, String token, int endIndexLastDelimiter) {
    boolean result = false;

    int openingBrackets = StringUtils.countOccurrencesOf(new String(Arrays.copyOfRange(chars, 0, i)),  "[");
    int closingBrackets = StringUtils.countOccurrencesOf(new String(Arrays.copyOfRange(chars, 0, i)),  "]");

    boolean inBrackets = (openingBrackets - closingBrackets > 0);

    if ((i - endIndexLastDelimiter >= this.delimiter.length()) && 
      (i >= token.length() - 1)) {
      String end = new String(chars, i - token.length() + 1, token.length());
      if (token.equals(end)) {
        if (inBrackets) {
          result = false;
        } else {
          result = true;
        }
      }
    }
    return result;
  }